Merge pull request #1400 from hapifhir/2023-08-gg-profile-code-generation

First cut at profile code generation
This commit is contained in:
Grahame Grieve 2023-08-20 22:11:52 +10:00 committed by GitHub
commit 55f4f42c94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1148 additions and 2 deletions

View File

@ -30,7 +30,7 @@ import org.hl7.fhir.utilities.Utilities;
* *** NOTE: This sub-system is still under development ***
*
* This subsystem takes a profile and creates a view of the profile that stitches
* all the parts together, and presents it as a seemless tree. There's two views:
* all the parts together, and presents it as a seamless tree. There's two views:
*
* - definition: A logical view of the contents of the profile
* - instance: a logical view of a resource that conforms to the profile

View File

@ -294,6 +294,26 @@ public abstract class PEDefinition {
return !"1".equals(definition.getBase().getMax());
}
public StructureDefinition getProfile() {
return profile;
}
public boolean isKeyElement() {
boolean selfKey = definition.getMustSupport() || definition.getMustHaveValue() || min() > 0 || definition.hasCondition();
if (isProfiled() && !selfKey) {
if (types() != null && types().size() > 0) {
for (PEDefinition child : children()) {
if (child.isKeyElement()) {
return true;
}
}
}
}
return selfKey;
}
}

View File

@ -13,6 +13,7 @@ import org.hl7.fhir.r5.model.Identifier;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.DateTimeType;
import org.hl7.fhir.r5.model.HumanName;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.Address;
import org.hl7.fhir.r5.model.PrimitiveType;
import org.hl7.fhir.r5.model.Quantity;
@ -240,4 +241,14 @@ public class PEInstance {
public Base getBase() {
return data;
}
public boolean hasChild(String name) {
PEDefinition child = byName(definition.children(), name);
List<Base> instances = builder.exec(resource, data, child.fhirpath());
return !instances.isEmpty();
}
public IWorkerContext getContext() {
return builder.getContext();
}
}

View File

@ -0,0 +1,549 @@
package org.hl7.fhir.r5.profilemodel.gen;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import java.util.ArrayList;
import java.util.Date;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Identifier;
import org.hl7.fhir.r5.model.Observation;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.profilemodel.PEBuilder;
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
import org.hl7.fhir.r5.profilemodel.gen.PECodeGenerator.ExtensionPolicy;
import org.hl7.fhir.r5.profilemodel.PEDefinition;
import org.hl7.fhir.r5.profilemodel.PEInstance;
import org.hl7.fhir.r5.profilemodel.PEType;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
public class PECodeGenerator {
public enum ExtensionPolicy {
None, Complexes, Primitives;
}
public static final SimpleDateFormat DATE_FORMAT() {
return new SimpleDateFormat("EEE, MMM d, yyyy HH:mmZ", new Locale("en", "US"));
}
private class PEGenClass {
private String name;
private String base;
private String doco;
private String url;
private boolean isResource;
private StringBuilder fields = new StringBuilder();
private StringBuilder load = new StringBuilder();
private StringBuilder save = new StringBuilder();
private StringBuilder clear = new StringBuilder();
private StringBuilder copy = new StringBuilder();
private StringBuilder accessors = new StringBuilder();
private StringBuilder hash = new StringBuilder();
public void genId() {
if (isResource) {
genField(true, "id", "String", "id", "", false, "");
genAccessors(true, false, "id", "String", "", "String", "String", "Id", "Ids", false, "", false);
genLoad(true, false, "id", "IdType", "", "String", "String", "Id", "Ids", false, false, null);
genClear(false, "id");
}
}
public void write(StringBuilder b) {
w(b);
w(b, "// Generated by the HAPI Java Profile Generator, "+DATE_FORMAT().format(new Date()));
w(b);
jdoc(b, doco, 0, true);
w(b, "public class "+name+" extends PEGeneratedBase {");
w(b);
if (url != null) {
w(b, " private static final String CANONICAL_URL = \""+url+"\";");
w(b);
}
w(b, fields.toString());
jdoc(b, "Parameter-less constructor. If you use this, the fixed values won't be filled out - they'll be missing. They'll be filled in if/when you call build, so they won't be missing from the resource, only from this particular object model", 2, true);
w(b, " public "+name+"() {");
w(b, " // todo");
w(b, " }");
w(b);
if (isResource) {
jdoc(b, "Construct an instance of the object, and fill out all the fixed values ", 2, true);
w(b, " public "+name+"(IWorkerContext context) {");
w(b, " workerContext = context;");
w(b, " PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);");
w(b, " PEInstance src = builder.buildPEInstance(CANONICAL_URL, builder.createResource(CANONICAL_URL, false));");
w(b, " load(src);");
w(b, " }");
w(b);
jdoc(b, "Populate an instance of the object based on this source object ", 2, true);
w(b, " public static "+name+" fromSource(IWorkerContext context, "+base+" source) {");
w(b, " "+name+" theThing = new "+name+"();");
w(b, " theThing.workerContext = context;");
w(b, " PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);");
w(b, " PEInstance src = builder.buildPEInstance(CANONICAL_URL, source);");
w(b, " theThing.load(src);");
w(b, " return theThing;");
w(b, " }");
w(b);
} else {
jdoc(b, "Used when loading other models ", 2, true);
w(b, " public static "+name+" fromSource(PEInstance source) {");
w(b, " "+name+" theThing = new "+name+"();");
w(b, " theThing.workerContext = source.getContext();");
w(b, " theThing.load(source);");
w(b, " return theThing;");
w(b, " }");
}
w(b);
w(b, " public void load(PEInstance src) {");
w(b, " clear();");
w(b, load.toString());
w(b, " }");
w(b);
if (isResource) {
jdoc(b, "Build an instance of the object based on this source object ", 2, true);
w(b, " public "+base+" build(IWorkerContext context) {");
w(b, " workerContext = context;");
w(b, " "+base+" theThing = new "+base+"();");
w(b, " PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);");
w(b, " PEInstance tgt = builder.buildPEInstance(CANONICAL_URL, theThing);");
w(b, " save(tgt, false);");
w(b, " return theThing;");
w(b, " }");
w(b);
jdoc(b, "Save this profile class into an existing resource (overwriting enything that exists in the profile) ", 2, true);
w(b, " public void save(IWorkerContext context, "+base+" dest, boolean nulls) {");
w(b, " workerContext = context;");
w(b, " PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);");
w(b, " PEInstance tgt = builder.buildPEInstance(CANONICAL_URL, dest);");
w(b, " save(tgt, nulls);");
w(b, " }");
w(b);
}
w(b, " public void save(PEInstance tgt, boolean nulls) {");
w(b, save.toString());
w(b, " }");
w(b);
w(b, accessors.toString());
w(b);
w(b, " public void clear() {");
w(b, clear.toString());
w(b, " }");
w(b);
w(b, "}");
}
private void defineField(PEDefinition source, PEDefinition field) {
if (field.types().size() == 1) {
StructureDefinition sd = workerContext.fetchTypeDefinition(field.types().get(0).getUrl());
if (sd != null) {
boolean isPrim = sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE;
boolean isAbstract = sd.getAbstract();
String name = field.name().replace("[x]", "");
String sname = name;
String type = null;
String init = "";
String ptype = type;
if (isPrim) {
// todo: are we extension-less?
type = Utilities.capitalize(field.types().get(0).getName()+"Type");
ptype = getPrimitiveType(sd);
} else {
type = field.types().get(0).getName();
}
String ltype = type;
if (field.isList()) {
ltype = "List<"+type+">";
init = "new ArrayList<>()";
if (!Utilities.existsInList(name, "contained")) {
name = Utilities.pluralize(name, 2);
}
}
String cname = Utilities.capitalize(name);
String csname = Utilities.capitalize(sname);
String nn = field.min() == 1 ? "// @NotNull" : "";
genField(isPrim, name, ptype, ltype, nn, field.isList(), field.shortDocumentation());
genAccessors(isPrim, isAbstract, name, type, init, ptype, ltype, cname, csname, field.isList(), field.documentation(), field.fixedValue());
genLoad(isPrim, isAbstract, name, type, init, ptype, ltype, cname, csname, field.isList(), field.fixedValue(), field.types().get(0));
genClear(field.isList(), name);
}
} else {
// ignoring polymorphics for now
}
}
private void genClear(boolean list, String name) {
w(clear, " "+name+" = null;");
}
private void genLoad(boolean isPrim, boolean isAbstract, String name, String type, String init, String ptype, String ltype, String cname, String csname, boolean isList, boolean isFixed, PEType typeInfo) {
if (isList) {
w(load, " for (PEInstance item : src.children(\""+name+"\")) {");
w(load, " "+name+".add(("+type+") item.asDataType());");
w(load, " }");
} else if (isPrim) {
w(load, " if (src.hasChild(\""+name+"\")) {");
w(load, " "+name+" = (("+type+") src.child(\""+name+"\").asDataType()).getValue();");
w(load, " }");
} else if (typeInfo != null && typeInfo.getUrl() != null && !typeInfo.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition")) {
w(load, " if (src.hasChild(\""+name+"\")) {");
w(load, " "+name+" = "+type+".fromSource(src.child(\""+name+"\"));");
w(load, " }");
} else {
w(load, " if (src.hasChild(\""+name+"\")) {");
w(load, " "+name+" = ("+type+") src.child(\""+name+"\").asDataType();");
w(load, " }");
}
}
private void genAccessors(boolean isPrim, boolean isAbstract, String name, String type, String init, String ptype, String ltype, String cname, String csname, boolean isList, String shortDoco, boolean isFixed) {
jdoc(accessors, doco, 2, true);
if (isPrim && extensionPolicy != ExtensionPolicy.Primitives && !isList) {
w(accessors, " public "+ptype+" get"+cname+"() {");
w(accessors, " return "+name+";");
w(accessors, " }");
w(accessors);
w(accessors, " public "+this.name+" set"+cname+"("+ptype+" value) {");
w(accessors, " this."+name+" = value;");
w(accessors, " return this;");
w(accessors, " }");
w(accessors);
w(accessors, " public boolean has"+cname+"() {");
w(accessors, " return "+name+" != null;");
w(accessors, " }");
} else {
if (isPrim && !isList) {
w(accessors, " public "+ptype+" get"+cname+"() {");
w(accessors, " if ("+name+" == null) { "+name+" = new "+type+"(); }");
w(accessors, " return "+name+".getValue();");
w(accessors, " }");
w(accessors, " public "+ltype+" get"+cname+"Element() {");
} else if (isAbstract && !isList) {
w(accessors, " public @Nullable "+ltype+" get"+cname+"() { // "+ltype+" is abstract ");
} else {
w(accessors, " public "+ltype+" get"+cname+"() {");
}
if (isList) {
w(accessors, " if ("+name+" == null) { "+name+" = "+init+"; }");
} else if (!isAbstract) {
w(accessors, " if ("+name+" == null) { "+name+" = new "+type+"(); }");
}
w(accessors, " return "+name+";");
w(accessors, " }");
w(accessors);
if (isList) {
w(accessors, " public boolean has"+cname+"() {");
w(accessors, " return "+name+" != null && !"+name+".isEmpty();");
w(accessors, " }");
w(accessors);
if (!isAbstract) {
w(accessors, " public "+type+" add"+csname+"() {");
w(accessors, " "+type+" theThing = new "+type+"();");
w(accessors, " get"+cname+"().add(theThing);");
w(accessors, " return theThing;");
w(accessors, " }");
w(accessors);
}
w(accessors, " public boolean has"+csname+"("+type+" item) {");
w(accessors, " return has"+cname+"() && "+name+".contains(item);");
w(accessors, " }");
w(accessors);
w(accessors, " public void remove"+csname+"("+type+" item) {");
w(accessors, " if (has"+csname+"(item)) {");
w(accessors, " "+name+".remove(item);");
w(accessors, " }");
w(accessors, " }");
w(accessors);
} else if (isPrim) {
if (!isFixed) {
w(accessors, " public "+this.name+" set"+cname+"("+ptype+" value) {");
w(accessors, " if ("+name+" == null) { "+name+" = new "+type+"(); }");
w(accessors, " "+name+".setValue(value);");
w(accessors, " return this;");
w(accessors, " }");
w(accessors, " public "+this.name+" set"+cname+"Element("+type+" value) {");
w(accessors, " this."+name+" = value;");
w(accessors, " return this;");
w(accessors, " }");
}
w(accessors, " public boolean has"+cname+"() {");
w(accessors, " return "+name+" != null && "+name+".hasValue();");
w(accessors, " }");
w(accessors);
} else {
if (!isFixed) {
w(accessors, " public "+this.name+" set"+cname+"("+type+" value) {");
w(accessors, " this."+name+" = value;");
w(accessors, " return this;");
w(accessors, " }");
}
w(accessors, " public boolean has"+cname+"() {");
w(accessors, " return "+name+" != null;");
w(accessors, " }");
}
}
w(accessors);
}
private void genField(boolean isPrim, String name, String ptype, String ltype, String nn, boolean isList, String shortDoco) {
// jdoc(fields, field.documentation(), 2, true);
if (isPrim && extensionPolicy != ExtensionPolicy.Primitives && !isList) {
w(fields, " private "+ptype+" "+name+";"+nn+" // "+shortDoco);
} else {
w(fields, " private "+ltype+" "+name+";"+nn+" // "+shortDoco);
}
}
}
private String folder;
private IWorkerContext workerContext;
private String canonical;
private String pkgName;
// options:
private ExtensionPolicy extensionPolicy;
private boolean narrative;
private boolean contained;
private boolean meta;
private String language;
private boolean keyELementsOnly;
public PECodeGenerator(IWorkerContext workerContext) {
super();
this.workerContext = workerContext;
}
public String getFolder() {
return folder;
}
public void setFolder(String folder) {
this.folder = folder;
}
public String getCanonical() {
return canonical;
}
public void setCanonical(String canonical) {
this.canonical = canonical;
}
public String getPkgName() {
return pkgName;
}
public void setPkgName(String pkgName) {
this.pkgName = pkgName;
}
public ExtensionPolicy getExtensionPolicy() {
return extensionPolicy;
}
public void setExtensionPolicy(ExtensionPolicy extensionPolicy) {
this.extensionPolicy = extensionPolicy;
}
public boolean isNarrative() {
return narrative;
}
public void setNarrative(boolean narrative) {
this.narrative = narrative;
}
public boolean isMeta() {
return meta;
}
public void setMeta(boolean meta) {
this.meta = meta;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public boolean isKeyELementsOnly() {
return keyELementsOnly;
}
public void setKeyELementsOnly(boolean keyELementsOnly) {
this.keyELementsOnly = keyELementsOnly;
}
public boolean isContained() {
return contained;
}
public void setContained(boolean contained) {
this.contained = contained;
}
private StringBuilder imports = new StringBuilder();
/**
* @throws IOException
*
*/
public void execute() throws IOException {
PEDefinition source = new PEBuilder(workerContext, PEElementPropertiesPolicy.EXTENSION, true).buildPEDefinition(canonical);
w(imports, "import java.util.List;");
w(imports, "import java.util.ArrayList;");
w(imports, "import javax.annotation.Nullable;");
w(imports, "import java.util.Date;\r\n");
w(imports);
w(imports, "import org.hl7.fhir.r5.context.IWorkerContext;");
w(imports, "import org.hl7.fhir.r5.model.*;");
w(imports, "import org.hl7.fhir.r5.profilemodel.PEBuilder;");
w(imports, "import org.hl7.fhir.r5.profilemodel.PEInstance;");
w(imports, "import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;");
w(imports, "import org.hl7.fhir.r5.profilemodel.gen.PEGeneratedBase;");
PEGenClass cls = genClass(source);
StringBuilder b = new StringBuilder();
w(b, "package "+pkgName+";");
w(b);
if (source.getProfile().hasCopyright()) {
jdoc(b, source.getProfile().getCopyright(), 0, false);
}
w(b, imports.toString());
cls.write(b);
TextFile.stringToFile(b.toString(), Utilities.path(folder, cls.name+".java"));
}
public void jdoc(StringBuilder b, String doco, int indent, boolean jdoc) {
if (!Utilities.noString(doco)) {
String pfx = Utilities.padLeft("", ' ', indent);
w(b, pfx+"/*"+(jdoc ? "*" : ""));
for (String line : doco.split("\\R")) {
for (String nl : naturalLines(line))
w(b, pfx+" * "+nl);
w(b, pfx+" *");
}
w(b, pfx+" */");
}
}
private List<String> naturalLines(String line) {
List<String> lines = new ArrayList<>();
while (line.length() > 80) {
int cutpoint = 80;
while (cutpoint > 0 && line.charAt(cutpoint) != ' ') {
cutpoint--;
}
if (cutpoint == 0) {
cutpoint = 80;
} else {
cutpoint++;
}
lines.add(line.substring(0, cutpoint));
line = line.substring(cutpoint);
}
lines.add(line);
return lines;
}
private void w(StringBuilder b) {
b.append("\r\n");
}
private void w(StringBuilder b, String line) {
b.append(line);
w(b);
}
private PEGenClass genClass(PEDefinition source) {
PEGenClass cls = new PEGenClass();
cls.name = source.getProfile().getName();
cls.base = source.getProfile().getType();
cls.doco = source.documentation();
cls.url = source.getProfile().getVersionedUrl();
cls.isResource = source.getProfile().getKind() == StructureDefinitionKind.RESOURCE;
cls.genId();
for (PEDefinition child : source.children()) {
if (genForField(source, child)) {
cls.defineField(source, child);
}
}
return cls;
}
private boolean genForField(PEDefinition source, PEDefinition child) {
if (child.definition().getBase().getPath().equals("Resource.meta")) {
return meta;
}
if (child.definition().getBase().getPath().equals("DomainResource.text")) {
return narrative;
}
if (child.definition().getBase().getPath().equals("Resource.language")) {
return language == null;
}
if (child.definition().getBase().getPath().endsWith(".extension") || child.definition().getBase().getPath().endsWith(".modifierExtension")) {
return extensionPolicy == ExtensionPolicy.Complexes;
}
if (child.definition().getBase().getPath().equals("DomainResource.contained")) {
return contained;
}
return !keyELementsOnly || (child.isKeyElement());
}
private String getPrimitiveType(StructureDefinition sd) {
if (sd.getType().equals("string"))
return "String";
if (sd.getType().equals("code"))
return "String";
if (sd.getType().equals("markdown"))
return "String";
if (sd.getType().equals("base64Binary"))
return "byte[]";
if (sd.getType().equals("uri"))
return "String";
if (sd.getType().equals("url"))
return "String";
if (sd.getType().equals("canonical"))
return "String";
if (sd.getType().equals("oid"))
return "String";
if (sd.getType().equals("integer"))
return "int";
if (sd.getType().equals("integer64"))
return "long";
if (sd.getType().equals("unsignedInt"))
return "int";
if (sd.getType().equals("positiveInt"))
return "int";
if (sd.getType().equals("boolean"))
return "boolean";
if (sd.getType().equals("decimal"))
return "BigDecimal";
if (sd.getType().equals("dateTime"))
return "Date";
if (sd.getType().equals("date"))
return "Date";
if (sd.getType().equals("id"))
return "String";
if (sd.getType().equals("instant"))
return "Date";
if (sd.getType().equals("time"))
return "String";
return "??";
}
}

View File

@ -1,12 +1,17 @@
package org.hl7.fhir.r5.profilemodel.gen;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.profilemodel.PEInstance;
public class PEGeneratedBase {
protected IWorkerContext workerContext;
@Deprecated
protected PEInstance instance;
@Deprecated
protected void removeChild(String name) {
PEInstance child = instance.child(name);
if (child != null) {
@ -14,16 +19,19 @@ public class PEGeneratedBase {
}
}
@Deprecated
protected void removeChildren(String name) {
for (PEInstance child : instance.children(name)) {
instance.removeChild(child);
}
}
@Deprecated
public PEInstance getInstance() {
return instance;
}
@Deprecated
public Base getData() {
return instance.getBase();
}

View File

@ -1,5 +1,6 @@
package org.hl7.fhir.r5.profiles;
import java.io.File;
import java.io.IOException;
import java.util.List;
@ -13,6 +14,8 @@ import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.profilemodel.PEDefinition;
import org.hl7.fhir.r5.profilemodel.PEInstance;
import org.hl7.fhir.r5.profilemodel.PEType;
import org.hl7.fhir.r5.profilemodel.gen.PECodeGenerator;
import org.hl7.fhir.r5.profilemodel.gen.PECodeGenerator.ExtensionPolicy;
import org.hl7.fhir.r5.profilemodel.gen.ProfileExample;
import org.hl7.fhir.r5.profilemodel.gen.ProfileExample.LOINCCodesForCholesterolInSerumPlasma;
import org.hl7.fhir.r5.profilemodel.gen.ProfileExample.ProfileExampleComplex;
@ -371,4 +374,21 @@ public class PETests {
}
@Test
public void testGenerate() throws IOException {
load();
PECodeGenerator gen = new PECodeGenerator(ctxt);
gen.setFolder(Utilities.path("[tmp]"));
gen.setCanonical("http://hl7.org/fhir/test/StructureDefinition/pe-profile1");
gen.setPkgName("org.hl7.fhir.r5.profiles");
gen.setExtensionPolicy(ExtensionPolicy.None);
gen.setNarrative(false);
gen.setMeta(false);
gen.setLanguage("en-AU");
gen.setContained(false);
gen.setKeyELementsOnly(true);
gen.execute();
gen.setCanonical("http://hl7.org/fhir/test/StructureDefinition/pe-profile2");
gen.execute();
}
}

View File

@ -0,0 +1,203 @@
package org.hl7.fhir.r5.profiles;
import java.util.List;
import java.util.ArrayList;
import javax.annotation.Nullable;
import java.util.Date;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.profilemodel.PEBuilder;
import org.hl7.fhir.r5.profilemodel.PEInstance;
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
import org.hl7.fhir.r5.profilemodel.gen.PEGeneratedBase;
import java.util.List;
import java.util.ArrayList;
import javax.annotation.Nullable;
import java.util.Date;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.profilemodel.PEBuilder;
import org.hl7.fhir.r5.profilemodel.PEInstance;
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
import org.hl7.fhir.r5.profilemodel.gen.PEGeneratedBase;
// Generated by the HAPI Java Profile Generator, Sun, Aug 20, 2023 19:05+1000
/**
* Test CodeableConcept Profile.
*
*/
public class TestDatatypeProfile extends PEGeneratedBase {
private static final String CANONICAL_URL = "http://hl7.org/fhir/test/StructureDefinition/pe-profile2|0.1";
private List<Coding> codings;// @NotNull // Code defined by a terminology system
private List<Coding> snomedcts;// @NotNull // Code defined by a terminology system
private List<Coding> loincs; // Code defined by a terminology system
private String text;// @NotNull // Plain text representation of the concept
/**
* Parameter-less constructor. If you use this, the fixed values won't be filled
* out - they'll be missing. They'll be filled in if/when you call build, so they
* won't be missing from the resource, only from this particular object model
*
*/
public TestDatatypeProfile() {
// todo
}
/**
* Used when loading other models
*
*/
public static TestDatatypeProfile fromSource(PEInstance source) {
TestDatatypeProfile theThing = new TestDatatypeProfile();
theThing.workerContext = source.getContext();
theThing.load(source);
return theThing;
}
public void load(PEInstance src) {
clear();
for (PEInstance item : src.children("codings")) {
codings.add((Coding) item.asDataType());
}
for (PEInstance item : src.children("snomedcts")) {
snomedcts.add((Coding) item.asDataType());
}
for (PEInstance item : src.children("loincs")) {
loincs.add((Coding) item.asDataType());
}
if (src.hasChild("text")) {
text = ((StringType) src.child("text").asDataType()).getValue();
}
}
public void save(PEInstance tgt, boolean nulls) {
}
/**
* Test CodeableConcept Profile.
*
*/
public List<Coding> getCodings() {
if (codings == null) { codings = new ArrayList<>(); }
return codings;
}
public boolean hasCodings() {
return codings != null && !codings.isEmpty();
}
public Coding addCoding() {
Coding theThing = new Coding();
getCodings().add(theThing);
return theThing;
}
public boolean hasCoding(Coding item) {
return hasCodings() && codings.contains(item);
}
public void removeCoding(Coding item) {
if (hasCoding(item)) {
codings.remove(item);
}
}
/**
* Test CodeableConcept Profile.
*
*/
public List<Coding> getSnomedcts() {
if (snomedcts == null) { snomedcts = new ArrayList<>(); }
return snomedcts;
}
public boolean hasSnomedcts() {
return snomedcts != null && !snomedcts.isEmpty();
}
public Coding addSnomedct() {
Coding theThing = new Coding();
getSnomedcts().add(theThing);
return theThing;
}
public boolean hasSnomedct(Coding item) {
return hasSnomedcts() && snomedcts.contains(item);
}
public void removeSnomedct(Coding item) {
if (hasSnomedct(item)) {
snomedcts.remove(item);
}
}
/**
* Test CodeableConcept Profile.
*
*/
public List<Coding> getLoincs() {
if (loincs == null) { loincs = new ArrayList<>(); }
return loincs;
}
public boolean hasLoincs() {
return loincs != null && !loincs.isEmpty();
}
public Coding addLoinc() {
Coding theThing = new Coding();
getLoincs().add(theThing);
return theThing;
}
public boolean hasLoinc(Coding item) {
return hasLoincs() && loincs.contains(item);
}
public void removeLoinc(Coding item) {
if (hasLoinc(item)) {
loincs.remove(item);
}
}
/**
* Test CodeableConcept Profile.
*
*/
public String getText() {
return text;
}
public TestDatatypeProfile setText(String value) {
this.text = value;
return this;
}
public boolean hasText() {
return text != null;
}
public void clear() {
codings = null;
snomedcts = null;
loincs = null;
text = null;
}
}

View File

@ -0,0 +1,335 @@
package org.hl7.fhir.r5.profiles;
/*
* Licensed under CC0 1.0 Universal (CC0 1.0).
*
* The person who associated a work with this deed has dedicated the work to the
* public domain by waiving all of his or her rights to the work worldwide under
* copyright law, including all related and neighboring rights, to the extent
* allowed by law.
*
* You can copy, modify, distribute and perform the work, even for commercial
* purposes, all without asking permission. See Other Information below.
*
*/
import java.util.List;
import java.util.ArrayList;
import javax.annotation.Nullable;
import java.util.Date;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.profilemodel.PEBuilder;
import org.hl7.fhir.r5.profilemodel.PEInstance;
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
import org.hl7.fhir.r5.profilemodel.gen.PEGeneratedBase;
// Generated by the HAPI Java Profile Generator, Sun, Aug 20, 2023 19:01+1000
/**
* Test Observation Profile.
*
*/
public class TestProfile extends PEGeneratedBase {
private static final String CANONICAL_URL = "http://hl7.org/fhir/test/StructureDefinition/pe-profile1|0.1";
private String id; //
private List<Identifier> identifiers; // Business Identifier for observation
private String status;// @NotNull // registered | preliminary | final | amended +
private CodeableConcept code;// @NotNull // Sexual Orientation
private Reference subject;// @NotNull // Who and/or what the observation is about
private Reference encounter; // Healthcare event during which this observation is made
private Date effective;// @NotNull // Clinically relevant time/time-period for observation
private List<Reference> performers; // Who is responsible for the observation
private TestDatatypeProfile valueCodeableConcept; // Sexual Orientation
/**
* Parameter-less constructor. If you use this, the fixed values won't be filled
* out - they'll be missing. They'll be filled in if/when you call build, so they
* won't be missing from the resource, only from this particular object model
*
*/
public TestProfile() {
// todo
}
/**
* Construct an instance of the object, and fill out all the fixed values
*
*/
public TestProfile(IWorkerContext context) {
workerContext = context;
PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);
PEInstance src = builder.buildPEInstance(CANONICAL_URL, builder.createResource(CANONICAL_URL, false));
load(src);
}
/**
* Populate an instance of the object based on this source object
*
*/
public static TestProfile fromSource(IWorkerContext context, Observation source) {
TestProfile theThing = new TestProfile();
theThing.workerContext = context;
PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);
PEInstance src = builder.buildPEInstance(CANONICAL_URL, source);
theThing.load(src);
return theThing;
}
public void load(PEInstance src) {
clear();
if (src.hasChild("id")) {
id = ((IdType) src.child("id").asDataType()).getValue();
}
for (PEInstance item : src.children("identifiers")) {
identifiers.add((Identifier) item.asDataType());
}
if (src.hasChild("status")) {
status = ((CodeType) src.child("status").asDataType()).getValue();
}
if (src.hasChild("code")) {
code = (CodeableConcept) src.child("code").asDataType();
}
if (src.hasChild("subject")) {
subject = (Reference) src.child("subject").asDataType();
}
if (src.hasChild("encounter")) {
encounter = (Reference) src.child("encounter").asDataType();
}
if (src.hasChild("effective")) {
effective = ((DateTimeType) src.child("effective").asDataType()).getValue();
}
for (PEInstance item : src.children("performers")) {
performers.add((Reference) item.asDataType());
}
if (src.hasChild("valueCodeableConcept")) {
valueCodeableConcept = TestDatatypeProfile.fromSource(src.child("valueCodeableConcept"));
}
}
/**
* Build an instance of the object based on this source object
*
*/
public Observation build(IWorkerContext context) {
workerContext = context;
Observation theThing = new Observation();
PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);
PEInstance tgt = builder.buildPEInstance(CANONICAL_URL, theThing);
save(tgt, false);
return theThing;
}
/**
* Save this profile class into an existing resource (overwriting enything that
* exists in the profile)
*
*/
public void save(IWorkerContext context, Observation dest, boolean nulls) {
workerContext = context;
PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);
PEInstance tgt = builder.buildPEInstance(CANONICAL_URL, dest);
save(tgt, nulls);
}
public void save(PEInstance tgt, boolean nulls) {
}
/**
* Test Observation Profile.
*
*/
public String getId() {
return id;
}
public TestProfile setId(String value) {
this.id = value;
return this;
}
public boolean hasId() {
return id != null;
}
/**
* Test Observation Profile.
*
*/
public List<Identifier> getIdentifiers() {
if (identifiers == null) { identifiers = new ArrayList<>(); }
return identifiers;
}
public boolean hasIdentifiers() {
return identifiers != null && !identifiers.isEmpty();
}
public Identifier addIdentifier() {
Identifier theThing = new Identifier();
getIdentifiers().add(theThing);
return theThing;
}
public boolean hasIdentifier(Identifier item) {
return hasIdentifiers() && identifiers.contains(item);
}
public void removeIdentifier(Identifier item) {
if (hasIdentifier(item)) {
identifiers.remove(item);
}
}
/**
* Test Observation Profile.
*
*/
public String getStatus() {
return status;
}
public TestProfile setStatus(String value) {
this.status = value;
return this;
}
public boolean hasStatus() {
return status != null;
}
/**
* Test Observation Profile.
*
*/
public CodeableConcept getCode() {
if (code == null) { code = new CodeableConcept(); }
return code;
}
public boolean hasCode() {
return code != null;
}
/**
* Test Observation Profile.
*
*/
public Reference getSubject() {
if (subject == null) { subject = new Reference(); }
return subject;
}
public TestProfile setSubject(Reference value) {
this.subject = value;
return this;
}
public boolean hasSubject() {
return subject != null;
}
/**
* Test Observation Profile.
*
*/
public Reference getEncounter() {
if (encounter == null) { encounter = new Reference(); }
return encounter;
}
public TestProfile setEncounter(Reference value) {
this.encounter = value;
return this;
}
public boolean hasEncounter() {
return encounter != null;
}
/**
* Test Observation Profile.
*
*/
public Date getEffective() {
return effective;
}
public TestProfile setEffective(Date value) {
this.effective = value;
return this;
}
public boolean hasEffective() {
return effective != null;
}
/**
* Test Observation Profile.
*
*/
public List<Reference> getPerformers() {
if (performers == null) { performers = new ArrayList<>(); }
return performers;
}
public boolean hasPerformers() {
return performers != null && !performers.isEmpty();
}
public Reference addPerformer() {
Reference theThing = new Reference();
getPerformers().add(theThing);
return theThing;
}
public boolean hasPerformer(Reference item) {
return hasPerformers() && performers.contains(item);
}
public void removePerformer(Reference item) {
if (hasPerformer(item)) {
performers.remove(item);
}
}
/**
* Test Observation Profile.
*
*/
public TestDatatypeProfile getValueCodeableConcept() {
if (valueCodeableConcept == null) { valueCodeableConcept = new TestDatatypeProfile(); }
return valueCodeableConcept;
}
public TestProfile setValueCodeableConcept(TestDatatypeProfile value) {
this.valueCodeableConcept = value;
return this;
}
public boolean hasValueCodeableConcept() {
return valueCodeableConcept != null;
}
public void clear() {
id = null;
identifiers = null;
status = null;
code = null;
subject = null;
encounter = null;
effective = null;
performers = null;
valueCodeableConcept = null;
}
}