more work on PE definitions

This commit is contained in:
Grahame Grieve 2022-12-28 16:11:45 +13:00
parent 50bc157ab9
commit d532af808b
13 changed files with 420 additions and 194 deletions

View File

@ -1497,6 +1497,8 @@ public class ProfileUtilities extends TranslatingUtilities {
res.setMaxLength(usage.getMaxLength());
if (!res.hasMustSupport() && usage.hasMustSupport())
res.setMustSupport(usage.getMustSupport());
if (!res.hasMustHaveValue() && usage.hasMustHaveValue())
res.setMustHaveValue(usage.getMustHaveValue());
if (!res.hasBinding() && usage.hasBinding())
res.setBinding(usage.getBinding().copy());
for (ElementDefinitionConstraintComponent c : usage.getConstraint())
@ -2217,6 +2219,18 @@ public class ProfileUtilities extends TranslatingUtilities {
else
derived.getMustSupportElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasMustHaveValueElement()) {
if (!(base.hasMustHaveValueElement() && Base.compareDeep(derived.getMustHaveValueElement(), base.getMustHaveValueElement(), false))) {
if (base.hasMustHaveValue() && base.getMustHaveValue() && !derived.getMustHaveValue()) {
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "Illegal constraint [must-have-value = false] when [must-have-value = true] in the base profile", ValidationMessage.IssueSeverity.ERROR));
}
base.setMustHaveValueElement(derived.getMustHaveValueElement().copy());
} else if (trimDifferential)
derived.setMustHaveValueElement(null);
else
derived.getMustHaveValueElement().setUserData(DERIVATION_EQUALS, true);
}
// profiles cannot change : isModifier, defaultValue, meaningWhenMissing

View File

@ -2392,8 +2392,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
@Override
public PEBuilder getProfiledElementBuilder(PEElementPropertiesPolicy elementProps) {
public PEBuilder getProfiledElementBuilder(PEElementPropertiesPolicy elementProps, boolean fixedProps) {
// TODO Auto-generated method stub
return new PEBuilder(this, elementProps);
return new PEBuilder(this, elementProps, fixedProps);
}
}

View File

@ -804,6 +804,6 @@ public interface IWorkerContext {
public String getSpecUrl();
public PEBuilder getProfiledElementBuilder(PEElementPropertiesPolicy elementProps);
public PEBuilder getProfiledElementBuilder(PEElementPropertiesPolicy elementProps, boolean fixedProps);
}

View File

@ -6,18 +6,21 @@ import java.util.List;
import org.apache.commons.lang3.NotImplementedException;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
import org.hl7.fhir.r5.context.ContextUtilities;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingComponent;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent;
import org.hl7.fhir.r5.model.ElementDefinition.SlicingRules;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.ResourceFactory;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.Utilities;
/**
@ -73,24 +76,27 @@ import org.hl7.fhir.utilities.Utilities;
*/
public class PEBuilder {
public enum PEElementPropertiesPolicy {
NONE, EXTENSION, EXTENSION_ID
}
private IWorkerContext context;
private ProfileUtilities pu;
private ContextUtilities cu;
private PEElementPropertiesPolicy elementProps;
private boolean fixedPropsDefault;
/**
* @param context - must be loaded with R5 definitions
* @param elementProps - whether to include Element.id and Element.extension in the tree. Recommended choice: Extension
*/
public PEBuilder(IWorkerContext context, PEElementPropertiesPolicy elementProps) {
public PEBuilder(IWorkerContext context, PEElementPropertiesPolicy elementProps, boolean fixedPropsDefault) {
super();
this.context = context;
this.elementProps = elementProps;
this.fixedPropsDefault = fixedPropsDefault;
pu = new ProfileUtilities(context, null, null);
cu = new ContextUtilities(context);
}
/**
@ -115,11 +121,7 @@ public class PEBuilder {
if (!profile.hasSnapshot()) {
throw new DefinitionException("Profile '"+url+"' does not have a snapshot");
}
StructureDefinition base = context.fetchTypeDefinition(profile.getType());
if (base == null) {
throw new DefinitionException("Unable to find base type '"+profile.getType()+"' for URL '"+url+"'");
}
return new PEDefinitionResource(this, base, profile);
return new PEDefinitionResource(this, profile);
}
/**
@ -144,11 +146,7 @@ public class PEBuilder {
if (!profile.hasSnapshot()) {
throw new DefinitionException("Profile '"+url+"' does not have a snapshot");
}
StructureDefinition base = context.fetchTypeDefinition(profile.getType());
if (base == null) {
throw new DefinitionException("Unable to find base type '"+profile.getType()+"' for URL '"+url+"'");
}
return new PEDefinitionResource(this, base, profile);
return new PEDefinitionResource(this, profile);
}
/**
@ -189,16 +187,45 @@ public class PEBuilder {
}
/**
* Given a profile, construct an empty resource of the type being profiled (to use as input
* to the buildPEInstance method
* For the current version of a profile, construct a resource and fill out any fixed or required elements
*
* No version, because the version doesn't change the type of the resource
* Note that fixed values are filled out irrespective of the value of fixedProps when the builder is created
*
* @param url identifies the profile
* @param version identifies the version of the profile
* @param meta whether to mark the profile in Resource.meta.profile
* @return constructed resource
*/
public Resource makeProfileBase(String url) {
StructureDefinition profile = getProfile(url);
return ResourceFactory.createResource(profile.getType());
public Resource createResource(String url, String version, boolean meta) {
PEDefinition definition = buildPEDefinition(url, version);
Resource res = ResourceFactory.createResource(definition.types().get(0).getType());
populateByProfile(res, definition);
if (meta) {
res.getMeta().addProfile(definition.profile.getUrl());
}
return res;
}
/**
* For the current version of a profile, construct a resource and fill out any fixed or required elements
*
* Note that fixed values are filled out irrespective of the value of fixedProps when the builder is created
*
* @param url identifies the profile
* @param meta whether to mark the profile in Resource.meta.profile
* @return constructed resource
*/
public Resource createResource(String url, boolean meta) {
PEDefinition definition = buildPEDefinition(url);
Resource res = ResourceFactory.createResource(definition.types().get(0).getType());
populateByProfile(res, definition);
if (meta) {
res.getMeta().addProfile(definition.profile.getUrl());
}
return res;
}
// -- methods below here are only used internally to the package
@ -210,41 +237,34 @@ public class PEBuilder {
private StructureDefinition getProfile(String url, String version) {
return context.fetchResource(StructureDefinition.class, url, version);
}
//
// protected List<PEDefinition> listChildren(boolean allFixed, StructureDefinition profileStructure, ElementDefinition definition, TypeRefComponent t, CanonicalType u) {
// // TODO Auto-generated method stub
// return null;
// }
protected List<PEDefinition> listChildren(StructureDefinition baseStructure, ElementDefinition baseDefinition,
StructureDefinition profileStructure, ElementDefinition profiledDefinition, TypeRefComponent t, CanonicalType u) {
// TODO Auto-generated method stub
return null;
}
protected List<PEDefinition> listChildren(StructureDefinition baseStructure, ElementDefinition baseDefinition, StructureDefinition profileStructure, ElementDefinition profileDefinition, String url, String... omitList) {
protected List<PEDefinition> listChildren(boolean allFixed, PEDefinition parent, StructureDefinition profileStructure, ElementDefinition definition, String url, String... omitList) {
StructureDefinition profile = profileStructure;
List<ElementDefinition> list = pu.getChildList(profile, profileDefinition);
if (profileDefinition.getType().size() == 1 || (!profileDefinition.getPath().contains(".")) || list.isEmpty()) {
assert url == null || checkType(profileDefinition, url);
List<ElementDefinition> list = pu.getChildList(profile, definition);
if (definition.getType().size() == 1 || (!definition.getPath().contains(".")) || list.isEmpty()) {
assert url == null || checkType(definition, url);
List<PEDefinition> res = new ArrayList<>();
if (list.size() == 0) {
profile = context.fetchResource(StructureDefinition.class, url);
list = pu.getChildList(profile, profile.getSnapshot().getElementFirstRep());
}
if (list.size() > 0) {
StructureDefinition base = baseStructure;
List<ElementDefinition> blist = pu.getChildList(baseStructure, baseDefinition);
if (blist.size() == 0) {
base = context.fetchTypeDefinition(url);
blist = pu.getChildList(base, base.getSnapshot().getElementFirstRep());
}
int i = 0;
while (i < list.size()) {
ElementDefinition defn = list.get(i);
if (include(defn)) {
ElementDefinition bdefn = getByName(blist, defn);
if (bdefn == null) {
throw new Error("no base definition for "+defn.getId());
}
if (passElementPropsCheck(bdefn) && !Utilities.existsInList(bdefn.getName(), omitList)) {
PEDefinitionElement pe = new PEDefinitionElement(this, base, bdefn, profileStructure, defn);
pe.setRecursing(profileDefinition == defn || (profile.getDerivation() == TypeDerivationRule.SPECIALIZATION && profile.getType().equals("Extension")));
if (!defn.getMax().equals("0") && (allFixed || include(defn))) {
if (passElementPropsCheck(defn) && !Utilities.existsInList(defn.getName(), omitList)) {
PEDefinitionElement pe = new PEDefinitionElement(this, profile, defn);
pe.setRecursing(definition == defn || (profile.getDerivation() == TypeDerivationRule.SPECIALIZATION && profile.getType().equals("Extension")));
if (cu.isPrimitiveDatatype(definition.getTypeFirstRep().getWorkingCode()) && "value".equals(pe.name())) {
pe.setMustHaveValue(definition.getMustHaveValue());
}
pe.setInFixedValue(definition.hasFixed() || definition.hasPattern() || parent.isInFixedValue());
if (defn.hasSlicing()) {
if (defn.getSlicing().getRules() != SlicingRules.CLOSED) {
res.add(pe);
@ -253,11 +273,11 @@ public class PEBuilder {
while (i < list.size() && list.get(i).getPath().equals(defn.getPath())) {
StructureDefinition ext = getExtensionDefinition(list.get(i));
if (ext != null) {
res.add(new PEDefinitionExtension(this, list.get(i).getSliceName(), baseStructure, getByName(blist, defn), profileStructure, list.get(i), defn, ext));
res.add(new PEDefinitionExtension(this, list.get(i).getSliceName(), profile, list.get(i), defn, ext));
} else if (isTypeSlicing(defn)) {
res.add(new PEDefinitionTypeSlice(this, list.get(i).getSliceName(), baseStructure, getByName(blist, defn), profileStructure, list.get(i), defn));
res.add(new PEDefinitionTypeSlice(this, list.get(i).getSliceName(), profile, list.get(i), defn));
} else {
res.add(new PEDefinitionSlice(this, list.get(i).getSliceName(), baseStructure, getByName(blist, defn), profileStructure, list.get(i), defn));
res.add(new PEDefinitionSlice(this, list.get(i).getSliceName(), profile, list.get(i), defn));
}
i++;
}
@ -301,24 +321,22 @@ public class PEBuilder {
}
private boolean include(ElementDefinition defn) {
if (defn.getMax().equals("0")) {
return false;
if (fixedPropsDefault) {
return true;
} else {
return !(defn.hasFixed() || defn.hasPattern());
}
if (defn.hasFixed() || defn.hasPattern()) {
return false;
}
return true;
}
protected List<PEDefinition> listSlices(StructureDefinition baseStructure, ElementDefinition baseDefinition, StructureDefinition profileStructure, ElementDefinition profileDefinition) {
List<ElementDefinition> list = pu.getSliceList(profileStructure, profileDefinition);
protected List<PEDefinition> listSlices(StructureDefinition profileStructure, ElementDefinition definition) {
List<ElementDefinition> list = pu.getSliceList(profileStructure, definition);
List<PEDefinition> res = new ArrayList<>();
for (ElementDefinition ed : list) {
if (profileStructure.getDerivation() == TypeDerivationRule.CONSTRAINT && profileStructure.getType().equals("Extension")) {
res.add(new PEDefinitionSubExtension(this, baseStructure, baseDefinition, profileStructure, ed));
res.add(new PEDefinitionSubExtension(this, profileStructure, ed));
} else {
PEDefinitionElement pe = new PEDefinitionElement(this, baseStructure, baseDefinition, profileStructure, ed);
pe.setRecursing(profileDefinition == ed || (profileStructure.getDerivation() == TypeDerivationRule.SPECIALIZATION && profileStructure.getType().equals("Extension")));
PEDefinitionElement pe = new PEDefinitionElement(this, profileStructure, ed);
pe.setRecursing(definition == ed || (profileStructure.getDerivation() == TypeDerivationRule.SPECIALIZATION && profileStructure.getType().equals("Extension")));
res.add(pe);
}
}
@ -350,9 +368,9 @@ public class PEBuilder {
}
private ElementDefinition getByName(List<ElementDefinition> blist, ElementDefinition defn) {
private ElementDefinition getByName(List<ElementDefinition> blist, String name) {
for (ElementDefinition ed : blist) {
if (ed.getName().equals(defn.getName())) {
if (name.equals(ed.getName())) {
return ed;
}
}
@ -360,7 +378,7 @@ public class PEBuilder {
}
public PEType makeType(TypeRefComponent t) {
protected PEType makeType(TypeRefComponent t) {
if (t.hasProfile()) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, t.getProfile().get(0).getValue());
if (sd == null) {
@ -373,7 +391,7 @@ public class PEBuilder {
}
}
public PEType makeType(TypeRefComponent t, CanonicalType u) {
protected PEType makeType(TypeRefComponent t, CanonicalType u) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, u.getValue());
if (sd == null) {
return new PEType(tail(u.getValue()), t.getWorkingCode(), u.getValue());
@ -383,7 +401,7 @@ public class PEBuilder {
}
public PEType makeType(String tn) {
protected PEType makeType(String tn) {
return new PEType(tn, tn, "http://hl7.org/fhir/StructureDefinition/"+ tn);
}
@ -391,14 +409,91 @@ public class PEBuilder {
return value.contains("/") ? value.substring(value.lastIndexOf("/")+1) : value;
}
public List<ElementDefinition> getChildren(StructureDefinition profileStructure, ElementDefinition profiledDefinition) {
return pu.getChildList(profileStructure, profiledDefinition);
protected List<ElementDefinition> getChildren(StructureDefinition profileStructure, ElementDefinition definition) {
return pu.getChildList(profileStructure, definition);
}
private PEInstance loadInstance(PEDefinition defn, Resource resource) {
throw new NotImplementedException("Not done yet");
}
public IWorkerContext getContext() {
return context;
}
protected void populateByProfile(Base base, PEDefinition definition) {
for (PEDefinition pe : definition.children(true)) {
if (pe.fixedValue()) {
if (pe.definition().hasPattern()) {
base.setProperty(pe.schemaName(), pe.definition().getPattern());
} else {
base.setProperty(pe.schemaName(), pe.definition().getFixed());
}
} else {
for (int i = 0; i < pe.min(); i++) {
Base b = null;
if (pe.schemaName().endsWith("[x]")) {
if (pe.types().size() == 1) {
b = base.addChild(pe.schemaName().replace("[x]", Utilities.capitalize(pe.types().get(0).getType())));
}
} else {
b = base.addChild(pe.schemaName());
}
if (b != null) {
populateByProfile(b, pe);
}
}
}
}
}
public String makeSliceExpression(StructureDefinition profile, ElementDefinitionSlicingComponent slicing, ElementDefinition definition) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(" and ");
for (ElementDefinitionSlicingDiscriminatorComponent d : slicing.getDiscriminator()) {
switch (d.getType()) {
case EXISTS:
throw new DefinitionException("The discriminator type 'exists' is not supported by the PEBuilder");
case PATTERN:
throw new DefinitionException("The discriminator type 'pattern' is not supported by the PEBuilder");
case POSITION:
throw new DefinitionException("The discriminator type 'position' is not supported by the PEBuilder");
case PROFILE:
throw new DefinitionException("The discriminator type 'profile' is not supported by the PEBuilder");
case TYPE:
throw new DefinitionException("The discriminator type 'type' is not supported by the PEBuilder");
case VALUE:
String path = d.getPath();
if (path.contains(".")) {
throw new DefinitionException("The discriminator path '"+path+"' is not supported by the PEBuilder");
}
ElementDefinition ed = getChildElement(profile, definition, path);
if (ed == null) {
throw new DefinitionException("The discriminator path '"+path+"' could not be resolved by the PEBuilder");
}
if (!ed.hasFixed()) {
throw new DefinitionException("The discriminator path '"+path+"' has no fixed value - this is not supported by the PEBuilder");
}
if (!ed.getFixed().isPrimitive()) {
throw new DefinitionException("The discriminator path '"+path+"' has a fixed value that is not a primitive ("+ed.getFixed().fhirType()+") - this is not supported by the PEBuilder");
}
b.append(path+" = '"+ed.getFixed().primitiveValue()+"'");
break;
case NULL:
throw new DefinitionException("The discriminator type 'null' is not supported by the PEBuilder");
default:
throw new DefinitionException("The discriminator type '??' is not supported by the PEBuilder");
}
}
return b.toString();
}
private ElementDefinition getChildElement(StructureDefinition profile, ElementDefinition definition, String path) {
List<ElementDefinition> elements = pu.getChildList(profile, definition);
if (elements.size() == 0) {
profile = definition.getTypeFirstRep().hasProfile() ? context.fetchResource(StructureDefinition.class, definition.getTypeFirstRep().getProfile().get(0).asStringValue()) :
context.fetchTypeDefinition(definition.getTypeFirstRep().getWorkingCode());
elements = pu.getChildList(profile, profile.getSnapshot().getElementFirstRep());
}
return getByName(elements, path);
}
}

View File

@ -5,6 +5,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.xmlbeans.impl.xb.xsdschema.All;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.StructureDefinition;
@ -13,40 +15,36 @@ public abstract class PEDefinition {
protected PEBuilder builder;
protected String name;
protected StructureDefinition baseStructure;
protected ElementDefinition baseDefinition;
protected StructureDefinition profileStructure;
protected ElementDefinition profiledDefinition;
protected StructureDefinition profile;
protected ElementDefinition definition;
protected List<PEType> types;
protected Map<String, List<PEDefinition>> children = new HashMap<>();
private boolean recursing;
private boolean mustHaveValue;
private boolean inFixedValue;
/**
* Don't create one of these directly - always use the public methods on ProfiledElementBuilder
*
* @param builder
* @param baseElement
* @param profiledElement
* @param data
*/
protected PEDefinition(PEBuilder builder, String name, ElementDefinition baseDefinition,
ElementDefinition profiledDefinition, Base data) {
super();
this.builder = builder;
this.name = name;
this.baseDefinition = baseDefinition;
this.profiledDefinition = profiledDefinition;
// this.data = data;
}
// /**
// * Don't create one of these directly - always use the public methods on ProfiledElementBuilder
// *
// * @param builder
// * @param baseElement
// * @param profiledElement
// * @param data
// */
// protected PEDefinition(PEBuilder builder, String name,
// ElementDefinition definition, Base data) {
// super();
// this.builder = builder;
// this.name = name;
// this.definition = definition;
//// this.data = data;
// }
protected PEDefinition(PEBuilder builder, String name, StructureDefinition base, ElementDefinition baseDefinition,
StructureDefinition profile, ElementDefinition profiledDefinition) {
protected PEDefinition(PEBuilder builder, String name, StructureDefinition profile, ElementDefinition definition) {
this.builder = builder;
this.name = name;
this.baseStructure = base;
this.baseDefinition = baseDefinition;
this.profileStructure = profile;
this.profiledDefinition = profiledDefinition;
this.profile = profile;
this.definition = definition;
}
@ -61,7 +59,7 @@ public abstract class PEDefinition {
* @return The name of the element in the resource (may be different to the slice name)
*/
public String schemaName() {
return baseDefinition.getName();
return definition.getName();
}
/**
@ -84,14 +82,14 @@ public abstract class PEDefinition {
* @return The minimum number of repeats allowed
*/
public int min() {
return profiledDefinition.getMin();
return mustHaveValue ? 1 : definition.getMin();
}
/**
* @return the maximum number of repeats allowed
*/
public int max() {
return profiledDefinition.getMax() == null || "*".equals(profiledDefinition.getMax()) ? Integer.MAX_VALUE : Integer.parseInt(profiledDefinition.getMax());
return definition.getMax() == null || "*".equals(definition.getMax()) ? Integer.MAX_VALUE : Integer.parseInt(definition.getMax());
}
/**
@ -100,7 +98,7 @@ public abstract class PEDefinition {
* Note that the profile definition might be the same as a base definition, when the tree runs off the end of what's profiled
*/
public ElementDefinition definition() {
return profiledDefinition;
return definition;
}
/**
@ -109,21 +107,26 @@ public abstract class PEDefinition {
* Note that the profile definition might be the same as a base definition, when the tree runs off the end of what's profiled
*/
public ElementDefinition baseDefinition() {
return baseDefinition;
String type = definition.getBase().getPath();
if (type.contains(".")) {
type= type.substring(0, type.indexOf("."));
}
StructureDefinition sd = builder.getContext().fetchTypeDefinition(type);
return sd.getSnapshot().getElementByPath(definition.getBase().getPath());
}
/**
* @return the short documentation of the definition (shown in the profile table view)
*/
public String shortDocumentation() {
return profiledDefinition.getShort();
return definition.getShort();
}
/**
* @return the full definition of the element (markdown syntax)
*/
public String documentation() {
return profiledDefinition.getDefinition();
return definition.getDefinition();
}
// /**
@ -142,16 +145,43 @@ public abstract class PEDefinition {
*
*/
public List<PEDefinition> children(String typeUrl) {
if (children.containsKey(typeUrl)) {
return children.get(typeUrl);
}
List<PEDefinition> res = new ArrayList<>();
makeChildren(typeUrl, res);
children.put(typeUrl, res);
return res;
return children(typeUrl, false);
}
protected abstract void makeChildren(String typeUrl, List<PEDefinition> children);
public List<PEDefinition> children(String typeUrl, boolean allFixed) {
if (children.containsKey(typeUrl+"$"+allFixed)) {
return children.get(typeUrl+"$"+allFixed);
}
List<PEDefinition> res = new ArrayList<>();
makeChildren(typeUrl, res, allFixed);
children.put(typeUrl+"$"+allFixed, res);
return res;
}
public List<PEDefinition> children() {
if (types().size() == 1) {
return children(types.get(0).getUrl(), false);
} else {
throw new DefinitionException("Attempt to get children for an element that doesn't have a single type (types = "+types()+")");
}
}
public List<PEDefinition> children(boolean allFixed) {
if (types().size() == 1) {
return children(types.get(0).getUrl(), allFixed);
} else {
throw new DefinitionException("Attempt to get children for an element that doesn't have a single type (types = "+types()+")");
}
}
/**
* @return True if the element has a fixed value. This will always be false if fixedProps = false when the builder is created
*/
public boolean fixedValue() {
return definition.hasFixed() || definition.hasPattern();
}
protected abstract void makeChildren(String typeUrl, List<PEDefinition> children, boolean allFixed);
@Override
public String toString() {
@ -171,8 +201,30 @@ public abstract class PEDefinition {
this.recursing = recursing;
}
protected boolean isMustHaveValue() {
return mustHaveValue;
}
protected void setMustHaveValue(boolean mustHaveValue) {
this.mustHaveValue = mustHaveValue;
}
/**
* @return true if this property is inside an element that has an assigned fixed value
*/
public boolean isInFixedValue() {
return inFixedValue;
}
protected void setInFixedValue(boolean inFixedValue) {
this.inFixedValue = inFixedValue;
}
/**
*
* This is public to support unit testing - there's no reason to use it otherwise
*
* @return used in the instance processor to differentiate slices
*/
public abstract String fhirpath();

View File

@ -6,18 +6,17 @@ import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
public class PEDefinitionElement extends PEDefinition {
public PEDefinitionElement(PEBuilder builder,
StructureDefinition baseStructure, ElementDefinition baseDefinition,
StructureDefinition profileStructure, ElementDefinition profileDefinition) {
super(builder, baseDefinition.getName(), baseStructure, baseDefinition, profileStructure, profileDefinition);
public PEDefinitionElement(PEBuilder builder, StructureDefinition profile, ElementDefinition definition) {
super(builder, definition.getName(), profile, definition);
}
@Override
public void listTypes(List<PEType> types) {
for (TypeRefComponent t : profiledDefinition.getType()) {
for (TypeRefComponent t : definition.getType()) {
if (t.hasProfile()) {
for (CanonicalType u : t.getProfile()) {
types.add(builder.makeType(t, u));
@ -29,13 +28,28 @@ public class PEDefinitionElement extends PEDefinition {
}
@Override
protected void makeChildren(String typeUrl, List<PEDefinition> children) {
children.addAll(builder.listChildren(baseStructure, baseDefinition, profileStructure, profiledDefinition, typeUrl));
protected void makeChildren(String typeUrl, List<PEDefinition> children, boolean allFixed) {
children.addAll(builder.listChildren(allFixed, this, profile, definition, typeUrl));
}
@Override
public String fhirpath() {
return baseDefinition.getName();
String base = definition.getName().replace("[x]", "");
if (definition.hasSlicing()) {
// get all the slices
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(" or ");
List<PEDefinition> slices = builder.listSlices(profile, definition);
// list all the fhirpaths
for (PEDefinition slice : slices) {
b.append("("+builder.makeSliceExpression(profile, definition.getSlicing(), slice.definition())+")");
}
if (b.count() == 0)
return base;
else
return base+".where(("+b.toString()+").not())";
} else {
return base;
}
}
}

View File

@ -15,11 +15,8 @@ public class PEDefinitionExtension extends PEDefinition {
private ElementDefinition eed;
private ElementDefinition ved;
public PEDefinitionExtension(PEBuilder builder, String name,
StructureDefinition baseStructure, ElementDefinition baseDefinition,
StructureDefinition profileStructure, ElementDefinition profileDefinition,
ElementDefinition sliceDefinition, StructureDefinition extension) {
super(builder, name, baseStructure, baseDefinition, profileStructure, profileDefinition);
public PEDefinitionExtension(PEBuilder builder, String name, StructureDefinition profile, ElementDefinition definition, ElementDefinition sliceDefinition, StructureDefinition extension) {
super(builder, name, profile, definition);
this.sliceDefinition = sliceDefinition;
this.extension= extension;
eed = extension.getSnapshot().getElementByPath("Extension.extension");
@ -44,14 +41,14 @@ public class PEDefinitionExtension extends PEDefinition {
}
@Override
protected void makeChildren(String typeUrl, List<PEDefinition> children) {
protected void makeChildren(String typeUrl, List<PEDefinition> children, boolean allFixed) {
if (ved.isRequired() || eed.isProhibited()) {
children.addAll(builder.listChildren(extension, ved, extension, ved, typeUrl));
children.addAll(builder.listChildren(allFixed, this, extension, ved, typeUrl));
} else {
if (eed.getSlicing().getRules() != SlicingRules.CLOSED) {
children.addAll(builder.listChildren(extension, eed, extension, eed, "http://hl7.org/fhir/StructureDefinition/Extension", "value[x]", "url"));
children.addAll(builder.listChildren(allFixed, this, extension, eed, "http://hl7.org/fhir/StructureDefinition/Extension", "value[x]", "url"));
}
children.addAll(builder.listSlices(extension, eed, extension, eed));
children.addAll(builder.listSlices(extension, eed));
}
}

View File

@ -6,23 +6,23 @@ import org.hl7.fhir.r5.model.StructureDefinition;
public class PEDefinitionResource extends PEDefinition {
public PEDefinitionResource(PEBuilder builder, StructureDefinition base, StructureDefinition profile) {
super(builder, profile.getName(), base, base.getSnapshot().getElementFirstRep(), profile, profile.getSnapshot().getElementFirstRep());
public PEDefinitionResource(PEBuilder builder, StructureDefinition profile) {
super(builder, profile.getName(), profile, profile.getSnapshot().getElementFirstRep());
}
@Override
public void listTypes(List<PEType> types) {
types.add(new PEType(profileStructure.getName(), profileStructure.getType(), profileStructure.getUrl()));
types.add(new PEType(profile.getName(), profile.getType(), profile.getUrl()));
}
@Override
protected void makeChildren(String typeUrl, List<PEDefinition> children) {
children.addAll(builder.listChildren(baseStructure, baseDefinition, profileStructure, profiledDefinition, null));
protected void makeChildren(String typeUrl, List<PEDefinition> children, boolean allFixed) {
children.addAll(builder.listChildren(allFixed, this, profile, definition, null));
}
@Override
public String fhirpath() {
return profileStructure.getType();
return profile.getType();
}

View File

@ -11,16 +11,14 @@ public class PEDefinitionSlice extends PEDefinition {
protected ElementDefinition sliceDefinition;
public PEDefinitionSlice(PEBuilder builder, String name, StructureDefinition baseStructure,
ElementDefinition baseDefinition, StructureDefinition profileStructure, ElementDefinition profileDefinition,
ElementDefinition sliceDefinition) {
super(builder, name, baseStructure, baseDefinition, profileStructure, profileDefinition);
public PEDefinitionSlice(PEBuilder builder, String name, StructureDefinition profile, ElementDefinition profileDefinition, ElementDefinition sliceDefinition) {
super(builder, name, profile, profileDefinition);
this.sliceDefinition = sliceDefinition;
}
@Override
public void listTypes(List<PEType> types) {
for (TypeRefComponent t : profiledDefinition.getType()) {
for (TypeRefComponent t : definition.getType()) {
if (t.hasProfile()) {
for (CanonicalType u : t.getProfile()) {
types.add(builder.makeType(t, u));
@ -32,13 +30,15 @@ public class PEDefinitionSlice extends PEDefinition {
}
@Override
protected void makeChildren(String typeUrl, List<PEDefinition> children) {
throw new Error("Not done yet");
protected void makeChildren(String typeUrl, List<PEDefinition> children, boolean allFixed) {
children.addAll(builder.listChildren(allFixed, this, profile, definition, typeUrl));
}
@Override
public String fhirpath() {
throw new Error("Not done yet");
String base = schemaName().replace("[x]", "");
String filter = builder.makeSliceExpression(profile, sliceDefinition.getSlicing(), definition);
return base+".where("+filter+")";
}
}

View File

@ -14,9 +14,9 @@ public class PEDefinitionSubExtension extends PEDefinition {
private ElementDefinition ved;
private ElementDefinition ued;
public PEDefinitionSubExtension(PEBuilder builder, StructureDefinition baseStructure, ElementDefinition baseDefinition, StructureDefinition profileStructure, ElementDefinition profileDefinition) {
super(builder, profileDefinition.getSliceName(), baseStructure, baseDefinition, profileStructure, profileDefinition);
List<ElementDefinition> childDefs = builder.getChildren(profileStructure, profiledDefinition);
public PEDefinitionSubExtension(PEBuilder builder, StructureDefinition profile, ElementDefinition definition) {
super(builder, definition.getSliceName(), profile, definition);
List<ElementDefinition> childDefs = builder.getChildren(profile, definition);
eed = getElementByName(childDefs, "extension");
ved = getElementByName(childDefs, "value[x]");
ued = getElementByName(childDefs, "url");
@ -49,14 +49,14 @@ public class PEDefinitionSubExtension extends PEDefinition {
}
@Override
protected void makeChildren(String typeUrl, List<PEDefinition> children) {
protected void makeChildren(String typeUrl, List<PEDefinition> children, boolean allFixed) {
if (ved.isRequired() || eed.isProhibited()) {
children.addAll(builder.listChildren(baseStructure, baseDefinition, profileStructure, ved, typeUrl));
children.addAll(builder.listChildren(allFixed, this, profile, ved, typeUrl));
} else {
if (eed.getSlicing().getRules() != SlicingRules.CLOSED) {
children.addAll(builder.listChildren(baseStructure, baseDefinition, profileStructure, eed, "http://hl7.org/fhir/StructureDefinition/Extension", "value[x]", "url"));
children.addAll(builder.listChildren(allFixed, this, profile, eed, "http://hl7.org/fhir/StructureDefinition/Extension", "value[x]", "url"));
}
children.addAll(builder.listSlices(baseStructure, baseDefinition, profileStructure, eed));
children.addAll(builder.listSlices(profile, eed));
}
}

View File

@ -6,21 +6,20 @@ import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
public class PEDefinitionTypeSlice extends PEDefinition {
protected ElementDefinition sliceDefinition;
public PEDefinitionTypeSlice(PEBuilder builder, String name, StructureDefinition baseStructure,
ElementDefinition baseDefinition, StructureDefinition profileStructure, ElementDefinition profileDefinition,
ElementDefinition sliceDefinition) {
super(builder, name, baseStructure, baseDefinition, profileStructure, profileDefinition);
public PEDefinitionTypeSlice(PEBuilder builder, String name, StructureDefinition profile, ElementDefinition definition, ElementDefinition sliceDefinition) {
super(builder, name, profile, definition);
this.sliceDefinition = sliceDefinition;
}
@Override
public void listTypes(List<PEType> types) {
for (TypeRefComponent t : profiledDefinition.getType()) {
for (TypeRefComponent t : definition.getType()) {
if (t.hasProfile()) {
for (CanonicalType u : t.getProfile()) {
types.add(builder.makeType(t, u));
@ -32,13 +31,18 @@ public class PEDefinitionTypeSlice extends PEDefinition {
}
@Override
protected void makeChildren(String typeUrl, List<PEDefinition> children) {
children.addAll(builder.listChildren(baseStructure, baseDefinition, profileStructure, profiledDefinition, typeUrl));
protected void makeChildren(String typeUrl, List<PEDefinition> children, boolean allFixed) {
children.addAll(builder.listChildren(allFixed, this, profile, definition, typeUrl));
}
@Override
public String fhirpath() {
throw new Error("Not done yet");
String base = definition.getName().replace("[x]", "");
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(" | ");
for (TypeRefComponent t : definition.getType()) {
b.append(base+".ofType("+t.getWorkingCode()+")");
}
return b.toString();
}
}

View File

@ -1,5 +1,6 @@
package org.hl7.fhir.r5.profilemodel;
import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.r5.model.Base;
@ -20,22 +21,36 @@ public abstract class PEInstance {
/**
* @return definition information about this instance data
*/
public abstract PEDefinition definition();
public PEDefinition definition() {
return definition;
}
/**
* @return the type of this element
*/
public abstract PEType type();
public PEType type() {
return definition.types().get(0);
}
/**
* @return all the children of this instance data
*/
public abstract List<PEInstance> children();
public List<PEInstance> children() {
List<PEInstance> res = new ArrayList<>();
return res;
}
/**
* @return all the children of this instance data for the named property
*/
public abstract List<PEInstance> children(String name);
public List<PEInstance> children(String name) {
// PEDefinition child = definition.childByName(name);
// if (child = null) {
//
// }
return null;
}
/**
* @return all the children of this instance data with the named property and the named type (for polymorphic

View File

@ -4,7 +4,9 @@ import java.io.IOException;
import java.util.List;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.model.Observation;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.profilemodel.PEDefinition;
import org.hl7.fhir.r5.profilemodel.PEType;
@ -32,7 +34,7 @@ public class PETests {
ctxt.cacheResource(new JsonParser().parse(TestingUtilities.loadTestResource("R5", "profiles", "pe-extension-simple.json")));
ctxt.cacheResource(new JsonParser().parse(TestingUtilities.loadTestResource("R5", "profiles", "pe-extension-complex.json")));
// ctxt.cacheResource(new JsonParser().parse(TestingUtilities.loadTestResource("R5", "profiles", "pe-profile2.json")));
ctxt.cacheResource(new JsonParser().parse(TestingUtilities.loadTestResource("R5", "profiles", "pe-profile2.json")));
ctxt.cacheResource(new JsonParser().parse(TestingUtilities.loadTestResource("R5", "profiles", "pe-profile1.json")));
}
}
@ -41,7 +43,7 @@ public class PETests {
@Test
public void testProfile() throws IOException {
load();
PEDefinition pe = new PEBuilder(ctxt, PEElementPropertiesPolicy.EXTENSION).buildPEDefinition("http://hl7.org/fhir/test/StructureDefinition/pe-profile1");
PEDefinition pe = new PEBuilder(ctxt, PEElementPropertiesPolicy.EXTENSION, true).buildPEDefinition("http://hl7.org/fhir/test/StructureDefinition/pe-profile1");
Assertions.assertEquals("TestProfile", pe.name());
Assertions.assertEquals("Observation", pe.schemaName());
@ -54,50 +56,69 @@ public class PETests {
Assertions.assertEquals("Test Observation Profile", pe.shortDocumentation());
Assertions.assertEquals("Test Observation Profile.", pe.documentation());
List<PEDefinition> children = pe.children("Observation");
checkElement(pe, "Observation", "TestProfile", 0, Integer.MAX_VALUE, "http://hl7.org/fhir/test/StructureDefinition/pe-profile1", 16);
checkElement(children.get(0), "id", "id", 0, 1, null, 0);
checkElement(children.get(1), "meta", "meta", 0, 1, "http://hl7.org/fhir/StructureDefinition/Meta", 7);
checkElement(children.get(2), "language", "language", 0, 1, "http://hl7.org/fhir/StructureDefinition/code", 2);
checkElement(children.get(3), "text", "text", 0, 1, "http://hl7.org/fhir/StructureDefinition/Narrative", 3);
checkElement(children.get(4), "contained", "contained", 0, Integer.MAX_VALUE, "http://hl7.org/fhir/StructureDefinition/Resource", 4);
checkElement(children.get(5), "extension", "extension", 0, Integer.MAX_VALUE, "http://hl7.org/fhir/StructureDefinition/Extension", 3);
checkElement(children.get(6), "extension", "simple", 0, 1, "http://hl7.org/fhir/StructureDefinition/code", 2);
checkElement(children.get(7), "extension", "complex", 0, 1, "http://hl7.org/fhir/StructureDefinition/Extension", 4);
checkElement(children.get(8), "identifier", "identifier", 0, 1, "http://hl7.org/fhir/StructureDefinition/Identifier", 7);
checkElement(children.get(9), "category", "category", 0, Integer.MAX_VALUE, "http://hl7.org/fhir/StructureDefinition/CodeableConcept", 3);
checkElement(children.get(10), "subject", "subject", 1, 1, "http://hl7.org/fhir/StructureDefinition/Reference", 5);
checkElement(children.get(11), "encounter", "encounter", 0, 1, "http://hl7.org/fhir/StructureDefinition/Reference", 5);
checkElement(children.get(12), "effective[x]", "effective[x]", 1, 1, "http://hl7.org/fhir/StructureDefinition/dateTime", 2);
checkElement(children.get(13), "issued", "issued", 0, 1, "http://hl7.org/fhir/StructureDefinition/instant", 2);
checkElement(children.get(14), "performer", "performer", 0, Integer.MAX_VALUE, "http://hl7.org/fhir/StructureDefinition/Reference", 5);
checkElement(children.get(15), "value[x]", "valueCodeableConcept", 0, 1, "http://hl7.org/fhir/StructureDefinition/CodeableConcept", 3);
List<PEDefinition> gchildren = children.get(7).children("http://hl7.org/fhir/StructureDefinition/Extension");
checkElement(gchildren.get(0), "extension", "extension", 0, Integer.MAX_VALUE, "http://hl7.org/fhir/StructureDefinition/Extension", 3);
checkElement(gchildren.get(1), "extension", "slice1", 0, 2, "http://hl7.org/fhir/StructureDefinition/Coding", 6);
checkElement(gchildren.get(2), "extension", "slice2", 0, Integer.MAX_VALUE, "http://hl7.org/fhir/StructureDefinition/string", 2);
checkElement(gchildren.get(3), "extension", "slice3", 1, 1, "http://hl7.org/fhir/StructureDefinition/Extension", 3);
checkElement(pe, "Observation", "TestProfile", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/test/StructureDefinition/pe-profile1", 18, "Observation");
checkElement(children.get(0), "id", "id", 0, 1, false, null, 0, "id");
checkElement(children.get(1), "meta", "meta", 0, 1, false, "http://hl7.org/fhir/StructureDefinition/Meta", 7, "meta");
checkElement(children.get(2), "language", "language", 0, 1, false, "http://hl7.org/fhir/StructureDefinition/code", 2, "language");
checkElement(children.get(3), "text", "text", 0, 1, false, "http://hl7.org/fhir/StructureDefinition/Narrative", 3, "text");
checkElement(children.get(4), "contained", "contained", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/StructureDefinition/Resource", 4, "contained");
checkElement(children.get(5), "extension", "extension", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/StructureDefinition/Extension", 3, "extension.where(((url = 'http://hl7.org/fhir/test/StructureDefinition/pe-extension-simple') or (url = 'http://hl7.org/fhir/test/StructureDefinition/pe-extension-complex')).not())");
checkElement(children.get(6), "extension", "simple", 0, 1, false, "http://hl7.org/fhir/StructureDefinition/code", 2, "extension('http://hl7.org/fhir/test/StructureDefinition/pe-extension-simple').value");
checkElement(children.get(7), "extension", "complex", 0, 1, false, "http://hl7.org/fhir/StructureDefinition/Extension", 4, "extension('http://hl7.org/fhir/test/StructureDefinition/pe-extension-complex').extension");
checkElement(children.get(8), "identifier", "identifier", 0, 1, false, "http://hl7.org/fhir/StructureDefinition/Identifier", 7, "identifier");
checkElement(children.get(9), "status", "status", 1, 1, true, "http://hl7.org/fhir/StructureDefinition/code", 2, "status");
checkElement(children.get(10), "category", "category", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/StructureDefinition/CodeableConcept", 3, "category");
checkElement(children.get(11), "code", "code", 1, 1, true, "http://hl7.org/fhir/StructureDefinition/CodeableConcept", 3, "code");
checkElement(children.get(12), "subject", "subject", 1, 1, false, "http://hl7.org/fhir/StructureDefinition/Reference", 5, "subject");
checkElement(children.get(13), "encounter", "encounter", 0, 1, false, "http://hl7.org/fhir/StructureDefinition/Reference", 5, "encounter");
checkElement(children.get(14), "effective[x]", "effective[x]", 1, 1, false, "http://hl7.org/fhir/StructureDefinition/dateTime", 2, "effective");
checkElement(children.get(15), "issued", "issued", 0, 1, false, "http://hl7.org/fhir/StructureDefinition/instant", 2, "issued");
checkElement(children.get(16), "performer", "performer", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/StructureDefinition/Reference", 5, "performer");
checkElement(children.get(17), "value[x]", "valueCodeableConcept", 0, 1, false, "http://hl7.org/fhir/test/StructureDefinition/pe-profile2", 4, "value.ofType(CodeableConcept)");
List<PEDefinition> ggchildren = gchildren.get(3).children("http://hl7.org/fhir/StructureDefinition/Extension");
checkElement(ggchildren.get(0), "extension", "extension", 0, Integer.MAX_VALUE, "http://hl7.org/fhir/StructureDefinition/Extension", 3);
checkElement(ggchildren.get(1), "extension", "slice3a", 0, 2, "http://hl7.org/fhir/StructureDefinition/Coding", 6);
checkElement(ggchildren.get(2), "extension", "slice3b", 0, Integer.MAX_VALUE, "http://hl7.org/fhir/StructureDefinition/string", 2);
List<PEDefinition> gchildren = children.get(11).children();
checkElement(gchildren.get(0), "extension", "extension", 0, Integer.MAX_VALUE, true, "http://hl7.org/fhir/StructureDefinition/Extension", 3, "extension");
checkElement(gchildren.get(1), "coding", "coding", 0, Integer.MAX_VALUE, true, "http://hl7.org/fhir/StructureDefinition/Coding", 6, "coding");
checkElement(gchildren.get(2), "text", "text", 0, 1, true, "http://hl7.org/fhir/StructureDefinition/string", 2, "text");
gchildren = children.get(17).children("http://hl7.org/fhir/test/StructureDefinition/pe-profile2");
checkElement(gchildren.get(0), "coding", "coding", 1, 2, false, "http://hl7.org/fhir/StructureDefinition/Coding", 6, "coding.where(((system = 'http://snomed.info/sct') or (system = 'http://loinc.org')).not())");
checkElement(gchildren.get(1), "coding", "snomedct", 1, 1, false, "http://hl7.org/fhir/StructureDefinition/Coding", 5, "coding.where(system = 'http://snomed.info/sct')");
checkElement(gchildren.get(2), "coding", "loinc", 0, 1, false, "http://hl7.org/fhir/StructureDefinition/Coding", 5, "coding.where(system = 'http://loinc.org')");
checkElement(gchildren.get(3), "text", "text", 1, 1, false, "http://hl7.org/fhir/StructureDefinition/string", 2, "text");
List<PEDefinition> ggchildren = gchildren.get(3).children("http://hl7.org/fhir/StructureDefinition/string");
checkElement(ggchildren.get(0), "extension", "extension", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/StructureDefinition/Extension", 3, "extension");
checkElement(ggchildren.get(1), "value", "value", 1, 1, false, null, 3, "value");
gchildren = children.get(7).children("http://hl7.org/fhir/StructureDefinition/Extension");
checkElement(gchildren.get(0), "extension", "extension", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/StructureDefinition/Extension", 3, "extension");
checkElement(gchildren.get(1), "extension", "slice1", 0, 2, false, "http://hl7.org/fhir/StructureDefinition/Coding", 6, "extension('slice1').value");
checkElement(gchildren.get(2), "extension", "slice2", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/StructureDefinition/string", 2, "extension('slice2').value");
checkElement(gchildren.get(3), "extension", "slice3", 1, 1, false, "http://hl7.org/fhir/StructureDefinition/Extension", 3, "extension('slice3').extension");
ggchildren = gchildren.get(3).children("http://hl7.org/fhir/StructureDefinition/Extension");
checkElement(ggchildren.get(0), "extension", "extension", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/StructureDefinition/Extension", 3, "extension");
checkElement(ggchildren.get(1), "extension", "slice3a", 0, 2, false, "http://hl7.org/fhir/StructureDefinition/Coding", 6, "extension('slice3a').value");
checkElement(ggchildren.get(2), "extension", "slice3b", 0, Integer.MAX_VALUE, false, "http://hl7.org/fhir/StructureDefinition/string", 2, "extension('slice3b').value");
}
private void checkElement(PEDefinition pe, String schemaName, String name, int min, int max, String type, int children) {
private void checkElement(PEDefinition pe, String schemaName, String name, int min, int max, boolean fixed, String type, int children, String fhirpath) {
Assertions.assertEquals(name, pe.name());
Assertions.assertEquals(schemaName, pe.schemaName());
Assertions.assertEquals(min, pe.min());
Assertions.assertEquals(max, pe.max());
Assertions.assertEquals(fixed, pe.fixedValue() || pe.isInFixedValue());
if (type != null) {
Assertions.assertEquals(1, pe.types().size());
Assertions.assertEquals(type, pe.types().get(0).getUrl());
List<PEDefinition> children2 = pe.children(type);
Assertions.assertEquals(children, children2.size());
}
Assertions.assertEquals(fhirpath, pe.fhirpath());
}
@ -105,7 +126,7 @@ public class PETests {
public void testUSPatientCore() throws IOException {
load();
PEDefinition pe = new PEBuilder(ctxt, PEElementPropertiesPolicy.EXTENSION_ID).buildPEDefinition("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient");
PEDefinition pe = new PEBuilder(ctxt, PEElementPropertiesPolicy.EXTENSION_ID, false).buildPEDefinition("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient");
Assertions.assertEquals("USCorePatientProfile", pe.name());
Assertions.assertEquals("Patient", pe.schemaName());
@ -243,7 +264,7 @@ public class PETests {
public void dumpUSPatientCore() throws IOException {
load();
PEDefinition pe = new PEBuilder(ctxt, PEElementPropertiesPolicy.NONE).buildPEDefinition("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient");
PEDefinition pe = new PEBuilder(ctxt, PEElementPropertiesPolicy.NONE, false).buildPEDefinition("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient");
dump(pe, "");
}
@ -266,4 +287,18 @@ public class PETests {
}
}
@Test
public void testCreate() throws IOException {
load();
Observation res = (Observation) new PEBuilder(ctxt, PEElementPropertiesPolicy.NONE, false).createResource("http://hl7.org/fhir/test/StructureDefinition/pe-profile1", true);
Assertions.assertEquals("http://hl7.org/fhir/test/StructureDefinition/pe-profile1", res.getMeta().getProfile().get(0).primitiveValue());
Assertions.assertEquals("final", res.getStatusElement().asStringValue());
Assertions.assertEquals("76690-7", res.getCode().getCodingFirstRep().getCode());
String json = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(res);
System.out.println(json);
}
}