more generator work

This commit is contained in:
Grahame Grieve 2019-12-28 21:19:35 +11:00
parent d23fd06797
commit 193e61999e
11 changed files with 1660 additions and 741 deletions

View File

@ -0,0 +1,295 @@
package org.hl7.fhir.core.generator.analysis;
import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.core.generator.codegen.Configuration;
import org.hl7.fhir.core.generator.engine.Definitions;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.SearchParameter;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.Enumerations.BindingStrength;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.utilities.Utilities;
public class Analyser {
private Definitions definitions;
private Configuration config;
public Analyser(Definitions definitions, Configuration config) {
this.definitions = definitions;
this.config = config;
}
public Analysis analyse(StructureDefinition sd) throws Exception {
Analysis res = new Analysis(definitions, sd);
res.setAncestor(definitions.getStructures().get(sd.getBaseDefinition()));
res.setAbstract(sd.getAbstract());
res.setInterface(sd.hasExtension("http://hl7.org/fhir/StructureDefinition/structuredefinition-interface"));
res.setClassName(sd.getName().equals("List") ? "ListResource" : sd.getName());
TypeInfo type = new TypeInfo();
type.setName(res.getClassName());
type.setAncestorName(res.getAncestor().getName());
res.getTypes().put(type.getName(), type);
res.setRootType(type);
sd.setUserData("java.type.info", type);
type.setDefn(sd.getSnapshot().getElementFirstRep());
type.setChildren(filterChildren(ProfileUtilities.getChildList(sd, type.getDefn())));
type.setInheritedChildren(getAbstractChildren(res.getAncestor()));
for (ElementDefinition e : type.getChildren()) {
scanNestedTypes(res, type, type.getName(), e);
}
if (sd.getKind() == StructureDefinitionKind.RESOURCE) {
res.setSearchParams(getSearchParams(sd.getName()));
}
for (ElementDefinition e : type.getChildren()) {
String nn = e.getUserString("java.type");
if (nn.startsWith("@")) {
ElementDefinition er = getElementForPath(sd, nn.substring(1));
if (!er.hasUserData("java.type")) {
throw new Exception("not found: "+er);
}
String nnn = er.getUserString("java.type");
e.setUserData("java.type", nnn);
e.setUserData("java.type.info", er.getUserData("java.type.info"));
}
}
return res;
}
protected List<ElementDefinition> filterChildren(List<ElementDefinition> childList) {
List<ElementDefinition> res = new ArrayList<>();
res.addAll(childList);
List<ElementDefinition> r = new ArrayList<>();
for (ElementDefinition t : childList) {
if (!t.getPath().equals(t.getBase().getPath())) {
r.add(t);
}
}
res.removeAll(r);
return res;
}
private List<ElementDefinition> getAbstractChildren(StructureDefinition structure) {
if (!structure.hasExtension("http://hl7.org/fhir/StructureDefinition/structuredefinition-interface")) {
return new ArrayList<>();
}
List<ElementDefinition> res = new ArrayList<>();
StructureDefinition sdb = definitions.getStructures().get(structure.getBaseDefinition());
res.addAll(getAbstractChildren(sdb));
res.addAll(filterChildren(ProfileUtilities.getChildList(structure, structure.getSnapshot().getElementFirstRep())));
return res;
}
private void scanNestedTypes(Analysis analysis, TypeInfo type, String path, ElementDefinition e) throws Exception {
String tn = null;
if (e.typeSummary().equals("code") && e.hasBinding()) {
ElementDefinitionBindingComponent cd = e.getBinding();
if (isEnum(cd)) {
ValueSet vs = definitions.getValuesets().get(cd.getValueSet());
if (vs != null) {
tn = getCodeListType(vs.getName());
EnumInfo ei = analysis.getEnums().get(tn);
if (ei == null) {
ei = new EnumInfo(tn);
analysis.getEnums().put(tn, ei);
ei.setValueSet(vs);
}
e.setUserData("java.type", "Enumeration<"+tn+">");
e.setUserData("java.enum", ei);
}
}
}
if (tn == null) {
if (e.getType().size() > 0 && !e.hasContentReference() && (!Utilities.existsInList(e.getType().get(0).getCode(), "Element", "BackboneElement"))) {
tn = getTypeName(e);
if (e.typeSummary().equals("xml:lang"))
tn = "CodeType";
if (e.typeSummary().equals("xhtml"))
tn = "XhtmlNode";
else if (e.getType().size() > 1)
tn ="DataType";
else if (definitions.hasPrimitiveType(tn))
tn = upFirst(tn)+"Type";
e.setUserData("java.type", tn);
} else {
if (e.hasContentReference()) {
ElementDefinition er = getElementForPath(analysis.getStructure(), e.getContentReference().substring(1));
tn = er.getUserString("java.type");
if (Utilities.noString(tn)) {
e.setUserData("java.type", "@"+er.getPath()); // have to resolve this later
} else {
e.setUserData("java.type", tn);
}
} else {
String cpath;
if (e.hasExtension("http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name")) {
tn = upFirst(e.getExtensionString("http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"))+"Component";
cpath = e.getExtensionString("http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name");
} else if (config.getIni().hasProperty("typenames", e.getPath())) {
tn = upFirst(config.getIni().getStringProperty("typenames", e.getPath()))+"Component";
cpath = config.getIni().getStringProperty("typenames", e.getPath());
} else {
tn = path+upFirst(getTitle(e.getName()))+"Component";
cpath = path+getTitle(e.getName());
}
if (tn.equals("Element"))
tn = "Element_";
if (analysis.getTypes().containsKey(tn)) {
char i = 'A';
while (analysis.getTypes().containsKey(tn+i)) {
i++;
}
tn = tn + i;
}
e.setUserData("java.type", tn);
tn = upFirst(tn);
TypeInfo ctype = new TypeInfo();
ctype.setName(tn);
analysis.getTypes().put(ctype.getName(), ctype);
analysis.getTypeList().add(ctype);
ctype.setDefn(e);
ctype.setAncestorName(e.typeSummary());
ctype.setChildren(filterChildren(ProfileUtilities.getChildList(analysis.getStructure(), ctype.getDefn())));
for (ElementDefinition c : ctype.getChildren()) {
scanNestedTypes(analysis, ctype, cpath, c);
}
}
}
}
}
protected boolean isEnum(ElementDefinitionBindingComponent cd) {
boolean ok = cd != null && cd.getStrength() == BindingStrength.REQUIRED;
if (ok) {
if (cd.getValueSet() != null) {
ValueSet vs = definitions.getValuesets().get(cd.getValueSet());
if (vs != null && vs.hasCompose() && vs.getCompose().getInclude().size() == 1) {
ConceptSetComponent inc = vs.getCompose().getIncludeFirstRep();
if (inc.hasSystem() && !inc.hasFilter() && !inc.hasConcept() && !(inc.getSystem().startsWith("http://hl7.org/fhir") || inc.getSystem().startsWith("http://terminology.hl7.org")))
ok = false;
}
}
}
return ok;
}
protected String getCodeListType(String binding) {
StringBuilder b = new StringBuilder();
boolean up = true;
for (char ch: binding.toCharArray()) {
if (ch == '-' || ch == ' ' || ch == '.')
up = true;
else if (up) {
b.append(Character.toUpperCase(ch));
up = false;
}
else
b.append(ch);
}
return "ResourceType".equals(b.toString()) ? "ResourceTypeEnum" : b.toString();
}
protected String getTypeName(ElementDefinition e) throws Exception {
if (e.getType().size() > 1) {
return "DataType";
} else if (e.getType().size() == 0) {
throw new Exception("not supported");
} else {
return getTypename(e.getType().get(0));
}
}
protected String getTypename(TypeRefComponent type) throws Exception {
if (type.hasExtension("http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type")) {
return type.getExtensionString("http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type");
} else {
return getTypeName(type.getCode());
}
}
protected String getTypeName(String tn) {
if (tn.equals("string")) {
return "StringType";
} else if (tn.equals("Any")) {
return "Reference";
} else if (tn.equals("SimpleQuantity")) {
return "Quantity";
} else if (isPrimitive(tn)) {
return getTitle(tn)+"Type";
} else {
return getTitle(tn);
}
}
protected String getTitle(String name) {
return Utilities.noString(name) ? "Value" : name.substring(0, 1).toUpperCase()+ name.substring(1);
}
protected boolean isPrimitive(String name) {
return definitions.getStructures().has(typeNs(name)) && definitions.getStructures().get(typeNs(name)).getKind() == StructureDefinitionKind.PRIMITIVETYPE;
}
private String upFirst(String name) {
return name.substring(0,1).toUpperCase()+name.substring(1);
}
private String typeNs(String name) {
return "http://hl7.org/fhir/StructureDefinition/"+name;
}
private ElementDefinition getElementForPath(StructureDefinition structure, String pathname) throws Exception {
String[] path = pathname.split("\\.");
if (!path[0].equals(structure.getName()))
throw new Exception("Element Path '"+pathname+"' is not legal in this context");
ElementDefinition res = null;
for (ElementDefinition t : structure.getSnapshot().getElement()) {
if (t.getPath().equals(pathname)) {
res = t;
}
}
if (res == null) {
throw new Exception("unable to resolve "+pathname);
}
return res;
}
private List<SearchParameter> getSearchParams(String name) {
List<SearchParameter> res = new ArrayList<>();
if (!Utilities.existsInList(name, "Resource")) {
for (SearchParameter sp : definitions.getSearchParams().getList()) {
boolean relevant = false;
for (CodeType c : sp.getBase()) {
if (c.getValue().equals(name)) {
relevant = true;
break;
}
}
if (relevant) {
res.add(sp);
}
}
}
return res;
}
}

View File

@ -0,0 +1,117 @@
package org.hl7.fhir.core.generator.analysis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hl7.fhir.core.generator.engine.Definitions;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.SearchParameter;
import org.hl7.fhir.r5.model.StructureDefinition;
public class Analysis {
// background
private Definitions definitions;
private StructureDefinition structure;
private String className;
private StructureDefinition ancestor;
private boolean isAbstract;
private boolean isInterface;
private List<TypeInfo> typeList = new ArrayList<>();
private TypeInfo rootType;
private Map<String, TypeInfo> types = new HashMap<>();
private Map<String, EnumInfo> enums = new HashMap<>();
private List<SearchParameter> searchParams = new ArrayList<>();
// private Map<ElementDefinition, String> typeNames = new HashMap<ElementDefinition, String>();
// private List<String> typeNameStrings = new ArrayList<String>();
// private List<ElementDefinition> enums = new ArrayList<ElementDefinition>();
// private List<String> enumNames = new ArrayList<String>();
// private List<ElementDefinition> strucs = new ArrayList<ElementDefinition>();
// private String classname;
public Analysis(Definitions definitions, StructureDefinition sd) {
this.definitions = definitions;
this.structure = sd;
}
public Definitions getDefinitions() {
return definitions;
}
public StructureDefinition getStructure() {
return structure;
}
public StructureDefinition getAncestor() {
return ancestor;
}
public void setAncestor(StructureDefinition ancestor) {
this.ancestor = ancestor;
}
public Map<String, TypeInfo> getTypes() {
return types;
}
public Map<String, EnumInfo> getEnums() {
return enums;
}
public boolean isAbstract() {
return isAbstract;
}
public void setAbstract(boolean isAbstract) {
this.isAbstract = isAbstract;
}
public boolean isInterface() {
return isInterface;
}
public void setInterface(boolean isInterface) {
this.isInterface = isInterface;
}
public List<SearchParameter> getSearchParams() {
return searchParams;
}
public void setSearchParams(List<SearchParameter> searchParams) {
this.searchParams = searchParams;
}
public String getClassName() {
return className;
}
public void setClassName(String name) {
this.className = name;
}
public String getName() {
return structure.getName();
}
public List<TypeInfo> getTypeList() {
return typeList;
}
public TypeInfo getRootType() {
return rootType;
}
public void setRootType(TypeInfo rootType) {
this.rootType = rootType;
}
}

View File

@ -0,0 +1,35 @@
package org.hl7.fhir.core.generator.analysis;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ValueSet;
public class EnumInfo {
private String name;
private ValueSet valueSet;
private boolean shared;
public EnumInfo(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ValueSet getValueSet() {
return valueSet;
}
public void setValueSet(ValueSet valueSet) {
this.valueSet = valueSet;
}
public boolean isShared() {
return shared;
}
public void setShared(boolean shared) {
this.shared = shared;
}
}

View File

@ -0,0 +1,48 @@
package org.hl7.fhir.core.generator.analysis;
import java.util.List;
import org.hl7.fhir.r5.model.ElementDefinition;
public class TypeInfo {
private ElementDefinition defn;
private String name;
private List<ElementDefinition> children;
private List<ElementDefinition> inheritedChildren;
private String ancestorName;
public ElementDefinition getDefn() {
return defn;
}
public void setDefn(ElementDefinition defn) {
this.defn = defn;
defn.setUserData("java.type.info", this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ElementDefinition> getChildren() {
return children;
}
public void setChildren(List<ElementDefinition> children) {
this.children = children;
}
public List<ElementDefinition> getInheritedChildren() {
return inheritedChildren;
}
public void setInheritedChildren(List<ElementDefinition> inheritedChildren) {
this.inheritedChildren = inheritedChildren;
}
public String getAncestorName() {
return ancestorName;
}
public void setAncestorName(String ancestorName) {
this.ancestorName = ancestorName;
}
}

View File

@ -69,7 +69,7 @@ public class JavaBaseGenerator extends OutputStreamWriter {
}
public String startLicenseValue() {
return "\r\n/*-\r\n"+config.getLicense()+"*/\r\n\r\n";
return "\r\n\r\n"+config.getLicense()+"\r\n\r\n";
}
public String startVMarkValue() {
@ -283,4 +283,23 @@ public class JavaBaseGenerator extends OutputStreamWriter {
}
return "ResourceType".equals(b.toString()) ? "ResourceTypeEnum" : b.toString();
}
protected ElementDefinition matchingInheritedElement(List<ElementDefinition> children, ElementDefinition m) {
if (children == null) {
return null;
}
String mtail = m.getPath().substring(m.getPath().indexOf("."));
for (ElementDefinition t : children) {
String ttail = t.getPath().substring(t.getPath().indexOf("."));
if (ttail.equals(mtail)) {
return t;
}
}
return null;
}
}

View File

@ -80,15 +80,14 @@ public class JavaEnumerationsGenerator extends JavaBaseGenerator {
for (String n : names) {
ValueSet vs = enums.get(n);
write("// "+n+": "+vs.getDescription());
ValueSet vsd = definitions.getValuesets().get(vs.getUrl());
write(vsd.getUserData("usages").toString());
write(vs.getUserData("usages").toString());
write("\r\n");
}
write("\r\n");
write("\r\n");
for (String n : names) {
ValueSet vs = enums.get(n);
generateEnum(n, vs);
generateEnum(n, (ValueSet) vs.getUserData("expansion"));
}
write("\r\n");
write("}\r\n");
@ -98,16 +97,9 @@ public class JavaEnumerationsGenerator extends JavaBaseGenerator {
private Map<String, ValueSet> scanForEnums() {
Map<String, ValueSet> res = new HashMap<>();
for (StructureDefinition sd : definitions.getStructures().getList()) {
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE) {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.hasBinding() && ed.getBinding().hasValueSet() && ed.getBinding().hasUserData("shared")) {
ValueSet vs = (ValueSet) ed.getBinding().getUserData("expansion");
if (vs != null) {
res.put(getCodeListType(vs.getName()), vs);
}
}
}
for (ValueSet vs : definitions.getValuesets().getSortedList()) {
if (vs.hasUserData("shared") && vs.hasUserData("expansion")) {
res.put(getCodeListType(vs.getName()), vs);
}
}
return res;

View File

@ -0,0 +1,117 @@
package org.hl7.fhir.core.generator.codegen;
/*
Copyright (c) 2011+, HL7, Inc
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hl7.fhir.core.generator.analysis.TypeInfo;
import org.hl7.fhir.core.generator.codegen.JavaBaseGenerator;
import org.hl7.fhir.core.generator.engine.Definitions;
import org.hl7.fhir.r5.model.ImplementationGuide.SPDXLicense;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import jdk.nashorn.internal.runtime.Specialization;
public class JavaFactoryGenerator extends JavaBaseGenerator {
public JavaFactoryGenerator(OutputStream out, Definitions definitions, Configuration configuration, Date genDate, String version) throws UnsupportedEncodingException {
super(out, definitions, configuration, version, genDate);
}
public void generate() throws Exception {
String template = config.getAdornments().get("ResourceFactory");
template = template.replace("{{license}}", config.getLicense());
template = template.replace("{{startMark}}", startVMarkValue());
template = template.replace("{{resource-factory}}", genResourceFactory());
template = template.replace("{{type-factory}}", genTypeFactory());
template = template.replace("{{case-factory}}", genCaseFactory());
write(template);
flush();
close();
}
private String genResourceFactory() {
StringBuilder b = new StringBuilder();
for (StructureDefinition sd : definitions.getStructures().getSortedList()) {
if (sd.getKind() == StructureDefinitionKind.RESOURCE && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && !sd.getAbstract()) {
String tn = ((TypeInfo) sd.getUserData("java.type.info")).getName();
b.append(" if (\""+sd.getName()+"\".equals(name))\r\n");
b.append(" return new "+tn+"();\r\n");
}
}
return b.toString();
}
private String genTypeFactory() {
StringBuilder b = new StringBuilder();
for (StructureDefinition sd : definitions.getStructures().getSortedList()) {
if (sd.getKind() == StructureDefinitionKind.COMPLEXTYPE && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && !sd.getAbstract()) {
String tn = ((TypeInfo) sd.getUserData("java.type.info")).getName();
b.append(" if (\""+sd.getName()+"\".equals(name))\r\n");
b.append(" return new "+tn+"();\r\n");
}
}
return b.toString();
}
private String genCaseFactory() {
StringBuilder b = new StringBuilder();
for (StructureDefinition sd : definitions.getStructures().getSortedList()) {
if (sd.getKind() == StructureDefinitionKind.RESOURCE && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && !sd.getAbstract()) {
String tn = ((TypeInfo) sd.getUserData("java.type.info")).getName();
b.append(" case "+Integer.toString(sd.getName().hashCode())+": return new "+tn+"();\r\n");
}
}
for (StructureDefinition sd : definitions.getStructures().getSortedList()) {
if (sd.getKind() == StructureDefinitionKind.COMPLEXTYPE && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && !sd.getAbstract()) {
String tn = ((TypeInfo) sd.getUserData("java.type.info")).getName();
b.append(" case "+Integer.toString(sd.getName().hashCode())+": return new "+tn+"();\r\n");
}
}
return b.toString();
}
}

View File

@ -0,0 +1,688 @@
package org.hl7.fhir.core.generator.codegen;
/*
Copyright (c) 2011+, HL7, Inc
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGed.
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hl7.fhir.core.generator.analysis.Analysis;
import org.hl7.fhir.core.generator.analysis.EnumInfo;
import org.hl7.fhir.core.generator.analysis.TypeInfo;
import org.hl7.fhir.core.generator.engine.Definitions;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.utilities.Utilities;
import jdk.internal.org.objectweb.asm.tree.analysis.AnalyzerException;
public class JavaParserJsonGenerator extends JavaBaseGenerator {
private StringBuilder parser = new StringBuilder();
private StringBuilder pregt = new StringBuilder();
private StringBuilder pregt2 = new StringBuilder();
private StringBuilder pregf = new StringBuilder();
private StringBuilder pregn = new StringBuilder();
private StringBuilder composer = new StringBuilder();
private StringBuilder creg = new StringBuilder();
private StringBuilder cregn = new StringBuilder();
private StringBuilder cregtn = new StringBuilder();
private StringBuilder cregtp = new StringBuilder();
private StringBuilder cregti = new StringBuilder();
public JavaParserJsonGenerator(OutputStream out, Definitions definitions, Configuration configuration, Date genDate, String version) throws UnsupportedEncodingException {
super(out, definitions, configuration, version, genDate);
}
public void seeClass(Analysis analysis) throws Exception {
generateParser(analysis);
generateComposer(analysis);
if (!analysis.isAbstract()) {
if (analysis.getStructure().getKind() == StructureDefinitionKind.COMPLEXTYPE) {
pregt.append(" } else if (json.has(prefix+\""+analysis.getName()+"\")) {\r\n return parse"+analysis.getRootType().getName()+"(json.getAsJsonObject(prefix+\""+analysis.getName()+"\"));\r\n");
pregt2.append(" } else if (type.equals(\""+analysis.getName()+"\")) {\r\n return parse"+analysis.getName()+"(json);\r\n");
cregtn.append(" } else if (type instanceof "+analysis.getName()+") {\r\n compose"+analysis.getName()+"(prefix+\""+analysis.getName()+"\", ("+analysis.getClassName()+") type);\r\n");
cregti.append(" } else if (type instanceof "+analysis.getName()+") {\r\n compose"+analysis.getName()+"Properties(("+analysis.getName()+") type);\r\n");
}
pregn.append(" if (json.has(prefix+\""+analysis.getName()+"\")) {\r\n return true;\r\n };\r\n");
if (analysis.getStructure().getKind() == StructureDefinitionKind.RESOURCE) {
pregf.append(" } else if (t.equals(\""+analysis.getName()+"\")) {\r\n return parse"+analysis.getClassName()+"(json);\r\n");
creg.append(" } else if (resource instanceof "+analysis.getClassName()+") {\r\n compose"+analysis.getClassName()+"(\""+analysis.getName()+"\", ("+analysis.getClassName()+")resource);\r\n");
cregn.append(" } else if (resource instanceof "+analysis.getClassName()+") {\r\n compose"+analysis.getClassName()+"(name, ("+analysis.getClassName()+")resource);\r\n");
}
}
}
public void generate() throws Exception {
String template = config.getAdornments().get("JsonParser");
template = template.replace("{{license}}", config.getLicense());
template = template.replace("{{startMark}}", startVMarkValue());
template = template.replace("{{parser}}", parser.toString());
template = template.replace("{{parse-resource}}", pregf.toString());
template = template.replace("{{parse-type-pfx}}", pregt.toString());
template = template.replace("{{parse-type}}", pregt2.toString());
template = template.replace("{{parse-has-type}}", pregn.toString());
template = template.replace("{{composer}}", composer.toString());
template = template.replace("{{compose-resource}}", creg.toString());
template = template.replace("{{compose-resource-named}}", cregn.toString());
template = template.replace("{{compose-type}}", cregtp.toString() + cregtn.toString());
template = template.replace("{{compose-type-inner}}", cregti.toString());
write(template);
flush();
close();
}
private String getAsJsonPrimitive(String code, boolean shrt) {
if ("boolean".equals(code))
return shrt ? "Boolean" : "java.lang.Boolean";
if ("decimal".equals(code))
return shrt ? "BigDecimal" : "java.math.BigDecimal";
if ("integer".equals(code) || "integer64".equals(code) )
return shrt ? "Long" : "java.lang.Long";
else
return "String";
}
private void generateParser(Analysis analysis) throws Exception {
if (analysis.isAbstract()) {
genInnerAbstract(analysis);
} else {
genInner(analysis, analysis.getRootType());
}
for (TypeInfo ti : analysis.getTypeList()) {
genInner(analysis, ti);
}
}
private void genInner(Analysis analysis, TypeInfo ti) throws IOException, Exception {
String tn = ti.getName();
String stn = (ti == analysis.getRootType() ? tn : analysis.getClassName()+"."+tn);
String pn = "parse"+tn;
if (stn.contains(".") && !pn.startsWith("parse"+analysis.getClassName())) {
pn = "parse"+analysis.getClassName()+tn;
}
boolean bUseOwner = false;
parser.append(" protected "+stn+" "+pn+"(JsonObject json) throws IOException, FHIRFormatError {\r\n");
parser.append(" "+stn+" res = new "+stn+"();\r\n");
parser.append(" "+pn+"Properties(json, res);\r\n");
parser.append(" return res;\r\n");
parser.append(" }\r\n\r\n");
parser.append(" protected void "+pn+"Properties(JsonObject json, "+stn+" res) throws IOException, FHIRFormatError {\r\n");
parser.append(" parse"+ti.getAncestorName()+"Properties(json, res);\r\n");
for (ElementDefinition e : ti.getChildren()) {
genElementParser(analysis, ti, e, bUseOwner, matchingInheritedElement(ti.getInheritedChildren(), e));
}
parser.append(" }\r\n\r\n");
}
private void genInnerAbstract(Analysis analysis) throws IOException, Exception {
String tn = analysis.getRootType().getName();
boolean bUseOwner = false;
parser.append(" protected void parse"+upFirst(tn).replace(".", "")+"Properties(JsonObject json, "+tn+" res) throws IOException, FHIRFormatError {\r\n");
parser.append(" parse"+analysis.getAncestor().getName()+"Properties(json, res);\r\n");
for (ElementDefinition e : analysis.getRootType().getChildren()) {
genElementParser(analysis, analysis.getRootType(), e, bUseOwner, null);
}
parser.append(" }\r\n\r\n");
}
private void genElementParser(Analysis analysis, TypeInfo ti, ElementDefinition ed, boolean bUseOwner, ElementDefinition inh) throws Exception {
String name = ed.getName();
String tn = ed.getUserString("java.type");
if (name.endsWith("[x]") || name.equals("[type]")) {
String en = name.endsWith("[x]") && !name.equals("[x]") ? name.replace("[x]", "") : "value";
String pfx = name.endsWith("[x]") ? name.replace("[x]", "") : "";
parser.append(" DataType "+getElementName(en, false)+" = parseType(\""+en+"\", json);\r\n");
parser.append(" if ("+getElementName(en, false)+" != null)\r\n");
parser.append(" res.set"+upFirst(getElementName(en, false))+"("+getElementName(en, false)+");\r\n");
} else {
String prsr = null;
String aprsr = null;
String anprsr = null;
if (ed.hasUserData("java.enum")) {
EnumInfo ei = (EnumInfo) ed.getUserData("java.enum"); // getCodeListType(cd.getBinding());
ValueSet vs = ei.getValueSet();
String en;
if (vs.hasUserData("shared")) {
en = "Enumerations."+ei.getName();
} else {
en = analysis.getClassName()+"."+ei.getName();
}
prsr = "parseEnumeration(json.get(\""+name+"\").getAsString(), "+en+".NULL, new "+en.substring(0, en.indexOf("."))+"."+en.substring(en.indexOf(".")+1)+"EnumFactory())"; // en+".fromCode(parseString(xpp))";
aprsr = "parseEnumeration(array.get(i).getAsString(), "+en+".NULL, new "+en.substring(0, en.indexOf("."))+"."+en.substring(en.indexOf(".")+1)+"EnumFactory())"; // en+".fromCode(parseString(xpp))";
anprsr = "parseEnumeration(null, "+en+".NULL, new "+en.substring(0, en.indexOf("."))+"."+en.substring(en.indexOf(".")+1)+"EnumFactory())"; // en+".fromCode(parseString(xpp))";
// parseEnumeration(xpp, Narratived.NarrativeStatus.additional, new Narratived.NarrativeStatusEnumFactory())
} else {
if (name.equals("extension")) {
name = "extension";
tn = "Extension";
}
if (tn.equals("XhtmlNode")) {
prsr = "parseXhtml(json.get(\""+name+"\").getAsString())";
} else if (tn.contains("Reference(")) {
prsr = "parseReference(json.getAsJsonObject(\""+name+"\"))";
aprsr = "parseReference(array.get(i).getAsJsonObject())";
anprsr = "parseReference(null)";
} else if (tn.contains("canonical(")) {
prsr = "parseCanonical(json.get(\""+name+"\").getAsString())";
aprsr = "parseCanonical(array.get(i).getAsString())";
anprsr = "parseCanonical(null)";
} else if (isPrimitive(ed.typeSummary())){
if (tn.endsWith("Type")) {
tn = tn.substring(0, tn.length()-4);
}
prsr = "parse"+upFirst(tn)+"(json.get(\""+name+"\").getAs"+getAsJsonPrimitive(ed.typeSummary(), true)+"())";
aprsr = "parse"+upFirst(tn)+"(array.get(i).getAs"+getAsJsonPrimitive(ed.typeSummary(), true)+"())";
anprsr = "parse"+upFirst(tn)+"(null)";
} else {
String pn = tn;
if ((ed.isInlineType() || ed.hasContentReference()) && !pn.startsWith(analysis.getClassName())) {
pn = analysis.getClassName()+pn;
}
prsr = "parse"+pn+"(json.getAsJsonObject(\""+name+"\"))";
aprsr = "parse"+pn+"(array.get(i).getAsJsonObject())";
anprsr = "parse"+pn+"(null)";
}
}
if (ed.unbounded()) {
if (isPrimitive(ed.typeSummary()) || ed.typeSummary().startsWith("canonical(")) {
parser.append(" if (json.has(\""+name+"\")) {\r\n");
parser.append(" JsonArray array = json.getAsJsonArray(\""+name+"\");\r\n");
parser.append(" for (int i = 0; i < array.size(); i++) {\r\n");
parser.append(" res.get"+upFirst(name)+"().add("+aprsr+");\r\n");
parser.append(" }\r\n");
parser.append(" };\r\n");
parser.append(" if (json.has(\"_"+name+"\")) {\r\n");
parser.append(" JsonArray array = json.getAsJsonArray(\"_"+name+"\");\r\n");
parser.append(" for (int i = 0; i < array.size(); i++) {\r\n");
parser.append(" if (i == res.get"+upFirst(name)+"().size())\r\n");
parser.append(" res.get"+upFirst(name)+"().add("+anprsr+");\r\n");
parser.append(" if (array.get(i) instanceof JsonObject) \r\n");
parser.append(" parseElementProperties(array.get(i).getAsJsonObject(), res.get"+upFirst(name)+"().get(i));\r\n");
parser.append(" }\r\n");
parser.append(" };\r\n");
} else {
parser.append(" if (json.has(\""+name+"\")) {\r\n");
parser.append(" JsonArray array = json.getAsJsonArray(\""+name+"\");\r\n");
parser.append(" for (int i = 0; i < array.size(); i++) {\r\n");
parser.append(" res.get"+upFirst(getElementName(name, false))+"().add("+aprsr+");\r\n");
parser.append(" }\r\n");
parser.append(" };\r\n");
}
} else if (inh != null && inh.unbounded()){
parser.append(" if (json.has(\""+name+"\"))\r\n");
if ((isPrimitive(ed.typeSummary()) || ed.typeSummary().startsWith("canonical(")) && !tn.equals("XhtmlNode")) {
parser.append(" res.add"+upFirst(getElementName(name, false))+"Element("+prsr+");\r\n");
parser.append(" if (json.has(\"_"+name+"\"))\r\n");
parser.append(" parseElementProperties(json.getAsJsonObject(\"_"+name+"\"), res.get"+upFirst(getElementName(name, false))+"ElementFirstRep());\r\n");
} else {
parser.append(" res.add"+upFirst(getElementName(name, false))+"("+prsr+");\r\n");
}
} else {
parser.append(" if (json.has(\""+name+"\"))\r\n");
if ((isPrimitive(ed.typeSummary()) || ed.typeSummary().startsWith("canonical(")) && !tn.equals("XhtmlNode")) {
parser.append(" res.set"+upFirst(getElementName(name, false))+"Element("+prsr+");\r\n");
parser.append(" if (json.has(\"_"+name+"\"))\r\n");
parser.append(" parseElementProperties(json.getAsJsonObject(\"_"+name+"\"), res.get"+upFirst(getElementName(name, false))+"Element());\r\n");
} else {
parser.append(" res.set"+upFirst(getElementName(name, false))+"("+prsr+");\r\n");
}
}
}
}
private String upFirst(String n) {
return n.substring(0,1).toUpperCase() + n.substring(1);
}
private void generateComposer(Analysis analysis) throws Exception {
if (analysis.isAbstract())
genInnerAbstractComposer(analysis);
else
genInnerComposer(analysis, analysis.getRootType());
for (TypeInfo ti : analysis.getTypeList()) {
genInnerComposer(analysis, ti);
}
}
private void genInnerAbstractComposer(Analysis analysis) throws IOException, Exception {
String tn = analysis.getRootType().getName();
composer.append(" protected void compose"+tn+"Properties("+tn+" element) throws IOException {\r\n");
composer.append(" compose"+analysis.getAncestor().getName()+"Properties(element);\r\n");
for (ElementDefinition e : analysis.getRootType().getChildren()) {
genElementComposer(analysis, analysis.getRootType(), e, null);
}
composer.append(" }\r\n\r\n");
}
private void genInnerComposer(Analysis analysis, TypeInfo ti) throws IOException, Exception {
String tn = ti.getName();
String stn = (ti == analysis.getRootType() ? tn : analysis.getClassName()+"."+tn);
composer.append(" protected void compose"+tn+"(String name, "+stn+" element) throws IOException {\r\n");
composer.append(" if (element != null) {\r\n");
boolean isResource = ti == analysis.getRootType() && analysis.getStructure().getKind() == StructureDefinitionKind.RESOURCE;
if (isResource) {
composer.append(" prop(\"resourceType\", name);\r\n");
} else {
composer.append(" open(name);\r\n");
}
composer.append(" compose"+upFirst(tn).replace(".", "")+"Properties(element);\r\n");
if (!isResource) {
composer.append(" close();\r\n");
}
composer.append(" }\r\n");
composer.append(" }\r\n\r\n");
composer.append(" protected void compose"+tn+"Properties("+stn+" element) throws IOException {\r\n");
composer.append(" compose"+ti.getAncestorName()+"Properties(element);\r\n");
for (ElementDefinition e : ti.getChildren()) {
genElementComposer(analysis, analysis.getRootType(), e, matchingInheritedElement(ti.getInheritedChildren(), e));
}
composer.append(" }\r\n\r\n");
}
private String pathClass(String tn) {
return tn.substring(0, tn.indexOf('.'));
}
private String pathNode(String tn) {
return tn.substring(tn.indexOf('.')+1);
}
private void genElementComposer(Analysis analysis, TypeInfo ti, ElementDefinition ed, ElementDefinition inh) throws Exception {
String name = ed.getName();
if (name.endsWith("[x]") || name.equals("[type]")) {
String en = name.endsWith("[x]") && !name.equals("[x]") ? name.replace("[x]", "") : "value";
String pfx = name.endsWith("[x]") ? name.replace("[x]", "") : "";
composer.append(" if (element.has"+upFirst(en)+"()) {\r\n");
composer.append(" composeType(\""+pfx+"\", element.get"+upFirst(en)+"());\r\n");
composer.append(" }\r\n");
} else {
String tn = ed.getUserString("java.type");
String comp = null;
String en = null;
boolean enShared = false;
if (ed.hasUserData("java.enum")) {
EnumInfo ei = (EnumInfo) ed.getUserData("java.enum"); // getCodeListType(cd.getBinding());
ValueSet vs = ei.getValueSet();
enShared = vs.hasUserData("shared");
if (enShared) {
en = "Enumerations."+ei.getName();
} else {
en = analysis.getClassName()+"."+ei.getName();
}
} else {
if (name.equals("extension")) {
name = "extension";
tn = "Extension";
}
if (tn.equals("XhtmlNode")) {
tn = "xhtml";
comp = "composeXhtml";
} else if (tn.equals("code")) {
tn = "Code";
comp = "composeCode";
} else if (tn.equals("instant")) {
tn = "Instant";
} else if (tn.contains("Reference(")) {
comp = "composeReference";
tn = "Reference";
} else if (tn.contains("canonical(")) {
comp = "composeCanonical";
tn = "CanonicalType";
} else if (tn.contains("(")) {
comp = "compose"+tn;
} else if (tn.startsWith(analysis.getName()) && !tn.equals(analysis.getClassName())) {
comp = "compose"+leaf(tn);
} else if (isPrimitive(ed)){
comp = "compose"+leaf(tn);
comp = comp.substring(0, comp.length()-4); // remove Type"
} else {
comp = "compose"+leaf(tn);
}
}
// if ((!contentsHaveId && typeIsSimple(e)) || ed.typeSummary().equals("xml:lang"))
// comp = comp+"Simple";
if (ed.unbounded()) {
tn = ed.getUserString("java.type");
if (tn.contains("Reference(")) {
comp = "composeReference";
tn = "Reference";
} else if (tn.contains("canonical(")) {
comp = "composeCanonical";
tn = "CanonicalType";
}
String stn = tn;
if (ed.isInlineType() || ed.hasContentReference()) {
stn = analysis.getClassName()+"."+tn;
}
composer.append(" if (element.has"+upFirst(getElementName(name, false))+"()) {\r\n");
if (en == null) {
if (tn.equals("String"))
tn = "StringType";
if (definitions.hasPrimitiveType(tn)) {
tn = upFirst(tn)+"Type";
}
if (isPrimitive(ed) || ed.typeSummary().startsWith("canonical(")) {
composer.append(" openArray(\""+name+"\");\r\n");
composer.append(" for ("+(tn.contains("(") ? stn : upFirst(tn))+" e : element.get"+upFirst(getElementName(name, false))+"()) \r\n");
composer.append(" "+comp+"Core(null, e, true);\r\n");
composer.append(" closeArray();\r\n");
composer.append(" if (anyHasExtras(element.get"+upFirst(getElementName(name, false))+"())) {\r\n");
composer.append(" openArray(\"_"+name+"\");\r\n");
composer.append(" for ("+(stn.contains("(") ? stn : upFirst(stn))+" e : element.get"+upFirst(getElementName(name, false))+"()) \r\n");
composer.append(" "+comp+"Extras(null, e, true);\r\n");
composer.append(" closeArray();\r\n");
composer.append(" }\r\n");
} else if (ed.typeSummary().equals("Resource")){
composer.append(" openArray(\""+name+"\");\r\n");
composer.append(" for ("+(stn.contains("(") ? tn : upFirst(tn))+" e : element.get"+upFirst(getElementName(name, false))+"()) {\r\n");
composer.append(" open(null);\r\n");
composer.append(" "+comp+"(e);\r\n");
composer.append(" close();\r\n");
composer.append(" }\r\n");
composer.append(" closeArray();\r\n");
} else {
composer.append(" openArray(\""+name+"\");\r\n");
composer.append(" for ("+(stn.contains("(") ? stn : upFirst(stn))+" e : element.get"+upFirst(getElementName(name, false))+"()) \r\n");
composer.append(" "+comp+"(null, e);\r\n");
composer.append(" closeArray();\r\n");
}
} else {
composer.append(" openArray(\""+name+"\");\r\n");
composer.append(" for (Enumeration<"+prepEnumName(en)+"> e : element.get"+upFirst(getElementName(name, false))+"()) \r\n");
composer.append(" composeEnumerationCore(null, e, new "+prepEnumName(en)+"EnumFactory(), true);\r\n");
composer.append(" closeArray();\r\n");
composer.append(" if (anyHasExtras(element.get"+upFirst(getElementName(name, false))+"())) {\r\n");
composer.append(" openArray(\"_"+name+"\");\r\n");
composer.append(" for (Enumeration<"+prepEnumName(en)+"> e : element.get"+upFirst(getElementName(name, false))+"()) \r\n");
composer.append(" composeEnumerationExtras(null, e, new "+prepEnumName(en)+"EnumFactory(), true);\r\n");
composer.append(" closeArray();\r\n");
composer.append(" }\r\n");
}
composer.append(" };\r\n");
} else if (en != null) {
composer.append(" if (element.has"+upFirst(getElementName(name, false))+"Element()) {\r\n");
if (enShared) {
composer.append(" composeEnumerationCore(\""+name+"\", element.get"+upFirst(getElementName(name, false))+"Element(), new "+prepEnumName(en)+"EnumFactory(), false);\r\n");
composer.append(" composeEnumerationExtras(\""+name+"\", element.get"+upFirst(getElementName(name, false))+"Element(), new "+prepEnumName(en)+"EnumFactory(), false);\r\n");
} else {
composer.append(" composeEnumerationCore(\""+name+"\", element.get"+upFirst(getElementName(name, false))+"Element(), new "+prepEnumName(en)+"EnumFactory(), false);\r\n");
composer.append(" composeEnumerationExtras(\""+name+"\", element.get"+upFirst(getElementName(name, false))+"Element(), new "+prepEnumName(en)+"EnumFactory(), false);\r\n");
}
composer.append(" }\r\n");
//composer.append(" composeString(\""+name+"\", element.get"+upFirst(getElementName(name, false))+"().toCode());\r\n");
} else if (ed.typeSummary().equals("Resource")){
composer.append(" if (element.has"+upFirst(getElementName(name, false))+"()) {\r\n");
composer.append(" open(\""+name+"\");\r\n");
composer.append(" "+comp+"(element.get"+upFirst(getElementName(name, false))+"());\r\n");
composer.append(" close();\r\n");
composer.append(" }\r\n");
} else if (!"xhtml".equals(ed.typeSummary()) && (isPrimitive(ed) || ed.typeSummary().startsWith("canonical("))) {
composer.append(" if (element.has"+upFirst(getElementName(name, false))+"Element()) {\r\n");
composer.append(" "+comp+"Core(\""+name+"\", element.get"+upFirst(getElementName(name, false))+"Element(), false);\r\n");
composer.append(" "+comp+"Extras(\""+name+"\", element.get"+upFirst(getElementName(name, false))+"Element(), false);\r\n");
composer.append(" }\r\n");
} else if (tn.equals("xhtml")) {
composer.append(" if (element.has"+upFirst(getElementName(name, false))+"()) {\r\n");
composer.append(" XhtmlNode node = element.getDiv();\r\n");
composer.append(" if (node.getNsDecl() == null) {\r\n");
composer.append(" node.attribute(\"xmlns\", XHTML_NS);\r\n");
composer.append(" }\r\n");
composer.append(" "+comp+"(\""+name+"\", node);\r\n");
composer.append(" }\r\n");
} else if (inh != null && inh.unbounded()){
composer.append(" if (element.has"+upFirst(getElementName(name, false))+"()) {\r\n");
composer.append(" "+comp+"(\""+name+"\", element.get"+upFirst(getElementName(name, false))+"FirstRep());\r\n");
composer.append(" }\r\n");
} else {
composer.append(" if (element.has"+upFirst(getElementName(name, false))+"()) {\r\n");
composer.append(" "+comp+"(\""+name+"\", element.get"+upFirst(getElementName(name, false))+"());\r\n");
composer.append(" }\r\n");
}
}
}
private boolean isPrimitive(ElementDefinition e) {
return definitions.hasPrimitiveType(e.typeSummary());
}
private String prepEnumName(String en) {
String[] parts = en.split("\\.");
if (parts.length == 1)
return upFirst(parts[0]);
else
return upFirst(parts[0])+'.'+upFirst(parts[1]);
}
private String leaf(String tn) {
return tn.startsWith("java.lang.") ? tn.substring(10) : tn;
}
//
// private boolean typeIsSimple(ElementDefn e) {
// String t = ed.typeSummary();
// return definitions.getPrimitives().containsKey(t);
// }
//
// private String typeName(ElementDefn root, ElementDefn elem, boolean formal) throws Exception {
// String t = elem.typeSummary();
// // if (usePrimitive && definitions.getPrimitives().containsKey(t)) {
// // if (t.equals("boolean"))
// // return formal ? "boolean" : "java.lang.Boolean";
// // else if (t.equals("integer"))
// // return "int";
// // else if (t.equals("integer64"))
// // return "long";
// // else if (t.equals("decimal"))
// // return formal ? "BigDecimal" : "BigDecimal";
// // else if (t.equals("base64Binary"))
// // return formal ? "byte[]" : "bytes";
// // else if (t.equals("instant"))
// // return formal ? "java.util.Calendar" : "Date";
// // else if (t.equals("uri"))
// // return formal ? "java.net.URI" : "Uri";
// // else if (t.equals("dateTime"))
// // return "DateTime";
// // else if (t.equals("date"))
// // return "Date";
// // else
// // return "String";
// //// return upFirst(t);
// // } else if (t.equals("xml:lang"))
// // return formal ? "string" : "Code";
// // else
// if (elem.usesCompositeType()) {
// if (typeNames.containsKey(elem) && typeNames.get(elem) != null)
// return typeNames.get(elem);
// else
// return root.getName();
// } else if (elem.getTypes().size() == 0) {
// return typeNames.get(elem);
// } else if (typeNames.containsKey(elem))
// return typeNames.get(elem);
// else
// return upFirst(t);
// }
//
// private void finishComposer() throws Exception {
// composer.append(" @Override\r\n");
// composer.append(" protected void composeResource(Resource resource) throws IOException {\r\n");
// composer.append(" "+reg.toString().substring(9));
// composer.append(" else if (resource instanceof Binary)\r\n");
// composer.append(" composeBinary(\"Binary\", (Binary)resource);\r\n");
// composer.append(" else\r\n");
// composer.append(" throw new Error(\"Unhandled resource type \"+resourced.getClass().getName());\r\n");
// composer.append(" }\r\n\r\n");
// composer.append(" protected void composeNamedReference(String name, Resource resource) throws IOException {\r\n");
// composer.append(" "+regn.toString().substring(9));
// composer.append(" else if (resource instanceof Binary)\r\n");
// composer.append(" composeBinary(name, (Binary)resource);\r\n");
// composer.append(" else\r\n");
// composer.append(" throw new Error(\"Unhandled resource type \"+resourced.getClass().getName());\r\n");
// composer.append(" }\r\n\r\n");
// composer.append(" protected void composeType(String prefix, Type type) throws IOException {\r\n");
// composer.append(" if (type == null)\r\n");
// composer.append(" ;\r\n");
// composer.append(regtp.toString());
// composer.append(regtn.toString());
// composer.append(" else\r\n");
// composer.append(" throw new Error(\"Unhandled type\");\r\n");
// composer.append(" }\r\n\r\n");
// composer.append(" protected void composeTypeInner(Type type) throws IOException {\r\n");
// composer.append(" if (type == null)\r\n");
// composer.append(" ;\r\n");
// composer.append(regti.toString());
// composer.append(" else\r\n");
// composer.append(" throw new Error(\"Unhandled type: \"+typed.fhirType());\r\n");
// composer.append(" }\r\n\r\n");
// //
// // composer.append(" private boolean nameIsTypeName(XmlPullParser xpp, String prefix) {\r\n");
// // composer.append(" "+regn.toString());
// // composer.append(" return false;\r\n");
// // composer.append(" }\r\n");
// //
// }
//
// private void scanNestedTypesComposer(ElementDefn root, String path, ElementDefn e) throws Exception {
// String tn = null;
// if (ed.typeSummary().equals("code") && ed.hasBinding()) {
// BindingSpecification cd = ed.getBinding();
// if (cd != null && cd.getBinding() == BindingSpecification.BindingMethod.CodeList) {
// tn = getCodeListType(cd.getValueSet().getName());
// if (!enumNames.contains(tn)) {
// enumNames.add(tn);
// enums.add(e);
// }
// typeNames.put(e, rootOf(path)+"."+tn);
// }
// if (cd != null && isEnum(cd)) {
// tn = getCodeListType(cd.getName());
// if (!enumNames.contains(tn)) {
// enumNames.add(tn);
// enums.add(e);
// }
// typeNames.put(e, rootOf(path)+"."+tn);
// }
// }
// if (tn == null) {
// if (ed.usesCompositeType()) {
// tn = typeNames.get(getElementForPath(root, ed.typeSummary().substring(1)));
// typeNames.put(e, tn);
// } else if (ed.getTypes().size() > 0) {
// tn = ed.typeSummary();
// TypeRef tr = ed.getTypes().get(0);
//
// if (tr.isUnboundGenericParam())
// tn = genparam;
// else if (tr.isXhtml())
// tn = "char[]";
// else if (tr.isWildcardType())
// tn ="Type";
// else if (tn.equals("xml:lang"))
// tn = "Code";
// else if (tn.equals("string"))
// tn = "String";
// if (tn.contains("<"))
// tn = tn.substring(0, tn.indexOf('<')+1)+tn.substring(tn.indexOf('<')+1, tn.indexOf('<')+2).toUpperCase()+tn.substring(tn.indexOf('<')+2);
// typeNames.put(e, tn);
// } else {
// if (ed.getDeclaredTypeName() != null)
// tn = ed.getDeclaredTypeName();
// else
// tn = upFirst(ed.getName());
// if (tn.equals("Element"))
// tn = "Element_";
// if (!ed.getName().equals("extension"))
// strucs.add(e);
// if (typeNameStrings.contains(tn)) {
// char i = 'A';
// while (typeNameStrings.contains(tn+i))
// i++;
// tn = tn + i;
// }
// typeNameStrings.add(tn);
// tn = path+"."+tn;
// typeNames.put(e, tn);
// for (ElementDefn c : ed.getElements()) {
// scanNestedTypesComposer(root, path, c);
// }
// }
// }
// }
//
// private String rootOf(String path) {
// int i = path.indexOf('.');
// return i == -1 ? path : path.substring(0, i);
// }
//
// @Override
// protected String getElementName(String name, boolean alone) {
// if (name.equals("[type]"))
// return "value";
// else if ((alone && GeneratorUtils.isJavaReservedWord(name)) || (!alone && name.equals("class")))
// return name+"_";
// else
// return name.replace("[x]", "");
// }
}

View File

@ -25,6 +25,7 @@ public class Definitions {
private CanonicalResourceManager<SearchParameter> searchParams = new CanonicalResourceManager<>(true);
private CanonicalResourceManager<CompartmentDefinition> compartments = new CanonicalResourceManager<>(true);
public CanonicalResourceManager<CodeSystem> getCodeSystems() {
return codeSystems;
}

View File

@ -9,8 +9,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hl7.fhir.core.generator.analysis.Analyser;
import org.hl7.fhir.core.generator.analysis.Analysis;
import org.hl7.fhir.core.generator.codegen.Configuration;
import org.hl7.fhir.core.generator.codegen.JavaEnumerationsGenerator;
import org.hl7.fhir.core.generator.codegen.JavaFactoryGenerator;
import org.hl7.fhir.core.generator.codegen.JavaParserJsonGenerator;
import org.hl7.fhir.core.generator.codegen.JavaResourceGenerator;
import org.hl7.fhir.core.generator.loader.DefinitionsLoader;
import org.hl7.fhir.r5.model.ValueSet;
@ -74,31 +78,83 @@ public class JavaCoreGenerator {
System.out.println(" .. Enumerations");
JavaEnumerationsGenerator egen = new JavaEnumerationsGenerator(new FileOutputStream(Utilities.path(dest, "src", "org", "hl7", "fhir", "r5", "model", "Enumerations.java")), master, config, date, npm.version());
egen.generate();
egen.close();
JavaFactoryGenerator fgen = new JavaFactoryGenerator(new FileOutputStream(Utilities.path(dest, "src", "org", "hl7", "fhir", "r5", "model", "ResourceFactory.java")), master, config, date, npm.version());
JavaParserJsonGenerator jgen = new JavaParserJsonGenerator(new FileOutputStream(Utilities.path(dest, "src", "org", "hl7", "fhir", "r5", "formats", "JsonParser.java")), master, config, date, npm.version());
for (StructureDefinition sd : master.getStructures().getList()) {
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE) {
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() == StructureDefinitionKind.COMPLEXTYPE) {
if (!Utilities.existsInList(sd.getName(), "Base", "PrimitiveType") && !sd.getName().contains(".") && sd.getAbstract()) {
String name = javaName(sd.getName());
System.out.println(" .. "+name);
Analyser jca = new Analyser(master, config);
Analysis analysis = jca.analyse(sd);
String fn = Utilities.path(dest, "src", "org", "hl7", "fhir", "r5", "model", name+".java");
JavaResourceGenerator gen = new JavaResourceGenerator(new FileOutputStream(fn), master, config, date, npm.version());
gen.generate(sd, name, getSearchParams(master, sd.getName()));
gen.generate(analysis);
gen.close();
jgen.seeClass(analysis);
}
}
}
for (StructureDefinition sd : master.getStructures().getList()) {
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE) {
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() == StructureDefinitionKind.COMPLEXTYPE) {
if (!Utilities.existsInList(sd.getName(), "Base", "PrimitiveType") && !sd.getName().contains(".") && !sd.getAbstract()) {
String name = javaName(sd.getName());
System.out.println(" .. "+name);
Analyser jca = new Analyser(master, config);
Analysis analysis = jca.analyse(sd);
String fn = Utilities.path(dest, "src", "org", "hl7", "fhir", "r5", "model", name+".java");
JavaResourceGenerator gen = new JavaResourceGenerator(new FileOutputStream(fn), master, config, date, npm.version());
gen.generate(sd, name, getSearchParams(master, sd.getName()));
gen.generate(analysis);
gen.close();
jgen.seeClass(analysis);
}
}
}
for (StructureDefinition sd : master.getStructures().getList()) {
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() == StructureDefinitionKind.RESOURCE) {
if (!Utilities.existsInList(sd.getName(), "Base", "PrimitiveType") && !sd.getName().contains(".") && sd.getAbstract()) {
String name = javaName(sd.getName());
System.out.println(" .. "+name);
Analyser jca = new Analyser(master, config);
Analysis analysis = jca.analyse(sd);
String fn = Utilities.path(dest, "src", "org", "hl7", "fhir", "r5", "model", name+".java");
JavaResourceGenerator gen = new JavaResourceGenerator(new FileOutputStream(fn), master, config, date, npm.version());
gen.generate(analysis);
gen.close();
jgen.seeClass(analysis);
}
}
}
for (StructureDefinition sd : master.getStructures().getList()) {
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() == StructureDefinitionKind.RESOURCE) {
if (!Utilities.existsInList(sd.getName(), "Base", "PrimitiveType") && !sd.getName().contains(".") && !sd.getAbstract()) {
String name = javaName(sd.getName());
System.out.println(" .. "+name);
Analyser jca = new Analyser(master, config);
Analysis analysis = jca.analyse(sd);
String fn = Utilities.path(dest, "src", "org", "hl7", "fhir", "r5", "model", name+".java");
JavaResourceGenerator gen = new JavaResourceGenerator(new FileOutputStream(fn), master, config, date, npm.version());
gen.generate(analysis);
gen.close();
jgen.seeClass(analysis);
}
}
}
System.out.println(" .. Factory");
fgen.generate();
fgen.close();
System.out.println(" .. JsonParser");
jgen.generate();
jgen.close();
System.out.println("Done");
}
@ -123,72 +179,33 @@ public class JavaCoreGenerator {
}
}
}
for (StructureDefinition sd : defns.getStructures().getList()) {
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE) {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.hasBinding() && ed.getBinding().hasValueSet()) {
ValueSet vs = defns.getValuesets().get(ed.getBinding().getValueSet());
boolean shared = false;
if (vs != null) {
List<String> list = (List<String>) vs.getUserData("usages");
if (list != null && list.size() > 1) {
shared = true;
}
}
if (config.getIni().hasProperty("shared", ed.getPath())) {
shared = config.getIni().getBooleanProperty("shared", ed.getPath());
}
if (shared) {
ed.getBinding().setUserData("shared", true);
}
}
}
for (ValueSet vs : defns.getValuesets().getList()) {
List<String> list = (List<String>) vs.getUserData("usages");
boolean shared = false;
if (list != null && list.size() > 1) {
shared = true;
}
if (config.getIni().hasProperty("shared", vs.getUrl())) {
shared = config.getIni().getBooleanProperty("shared", vs.getUrl());
}
if (shared) {
vs.setUserData("shared", true);
}
}
}
private List<SearchParameter> getSearchParams(Definitions defns, String name) {
List<SearchParameter> res = new ArrayList<>();
if (!Utilities.existsInList(name, "Resource")) {
for (SearchParameter sp : defns.getSearchParams().getList()) {
boolean relevant = false;
for (CodeType c : sp.getBase()) {
if (c.getValue().equals(name)) {
relevant = true;
break;
}
}
if (relevant) {
res.add(sp);
}
}
}
return res;
}
private String javaName(String name) {
return "List".equals(name) ? "ListResource" : name;
}
private void updateExpansions(Definitions master, Definitions expansions) {
for (StructureDefinition sd : master.getStructures().getList()) {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.hasBinding() && ed.getBinding().hasValueSet()) {
String ref = ed.getBinding().getValueSet();
if (ref.contains("|")) {
ref = ref.substring(0, ref.indexOf("|"));
}
ValueSet exp = expansions.getValuesets().get(ref);
if (exp != null) {
ed.getBinding().setUserData("expansion", exp);
}
}
for (ValueSet vs: master.getValuesets().getList()) {
ValueSet vse = expansions.getValuesets().get(vs.getUrl());
if (vse != null) {
vs.setUserData("expansion", vse);
}
}
}
}