finish R5 code generator
This commit is contained in:
parent
1131ac236e
commit
f262236b87
|
@ -364,45 +364,45 @@ public class XmlParser extends XmlParserBase {
|
|||
throw new IOException("prefix == null!");
|
||||
} else if (xpp == null) {
|
||||
throw new IOException("xpp == null!");
|
||||
} else if (xpp.getName().equals(prefix+"date")) {
|
||||
} else if (xpp.getName().equals(prefix+"Date")) {
|
||||
return parseDate(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"dateTime")) {
|
||||
} else if (xpp.getName().equals(prefix+"DateTime")) {
|
||||
return parseDateTime(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"code")) {
|
||||
} else if (xpp.getName().equals(prefix+"Code")) {
|
||||
return parseCode(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"string")) {
|
||||
} else if (xpp.getName().equals(prefix+"String")) {
|
||||
return parseString(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"integer")) {
|
||||
} else if (xpp.getName().equals(prefix+"Integer")) {
|
||||
return parseInteger(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"integer64")) {
|
||||
} else if (xpp.getName().equals(prefix+"Integer64")) {
|
||||
return parseInteger64(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"oid")) {
|
||||
} else if (xpp.getName().equals(prefix+"Oid")) {
|
||||
return parseOid(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"canonical")) {
|
||||
} else if (xpp.getName().equals(prefix+"Canonical")) {
|
||||
return parseCanonical(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"uri")) {
|
||||
} else if (xpp.getName().equals(prefix+"Uri")) {
|
||||
return parseUri(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"uuid")) {
|
||||
} else if (xpp.getName().equals(prefix+"Uuid")) {
|
||||
return parseUuid(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"url")) {
|
||||
} else if (xpp.getName().equals(prefix+"Url")) {
|
||||
return parseUrl(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"instant")) {
|
||||
} else if (xpp.getName().equals(prefix+"Instant")) {
|
||||
return parseInstant(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"boolean")) {
|
||||
} else if (xpp.getName().equals(prefix+"Boolean")) {
|
||||
return parseBoolean(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"base64Binary")) {
|
||||
} else if (xpp.getName().equals(prefix+"Base64Binary")) {
|
||||
return parseBase64Binary(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"unsignedInt")) {
|
||||
} else if (xpp.getName().equals(prefix+"UnsignedInt")) {
|
||||
return parseUnsignedInt(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"markdown")) {
|
||||
} else if (xpp.getName().equals(prefix+"Markdown")) {
|
||||
return parseMarkdown(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"time")) {
|
||||
} else if (xpp.getName().equals(prefix+"Time")) {
|
||||
return parseTime(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"id")) {
|
||||
} else if (xpp.getName().equals(prefix+"Id")) {
|
||||
return parseId(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"positiveInt")) {
|
||||
} else if (xpp.getName().equals(prefix+"PositiveInt")) {
|
||||
return parsePositiveInt(xpp);
|
||||
} else if (xpp.getName().equals(prefix+"decimal")) {
|
||||
} else if (xpp.getName().equals(prefix+"Decimal")) {
|
||||
return parseDecimal(xpp);
|
||||
{{parse-type-prefix}}
|
||||
} else {
|
||||
|
|
|
@ -14,9 +14,10 @@ To test the generation:
|
|||
* make sure that project is not in the build path for the generator itself, which depends on the production R5 code
|
||||
* run the generation
|
||||
* refresh etc and make sure that the compiler is happy
|
||||
* copy the JUnit tests ...
|
||||
* copy the JUnit tests RoundTripTests into the copy project, update the constants, and execute it
|
||||
* check all the tests pass, and inspect a sampling of the results for consistency
|
||||
|
||||
Configuring the Generation
|
||||
Configuring the Generation Output
|
||||
|
||||
The most common reason to alter the generation is to add additional utility routines/enhanceements to the generated classes.
|
||||
To do this, edit on the one of the templates in the configuration directory - xx.java, where xx is the class name (may include
|
||||
|
|
|
@ -43,6 +43,8 @@ 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.Enumeration;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
|
@ -167,9 +169,10 @@ public class JavaParserJsonGenerator extends JavaBaseGenerator {
|
|||
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);
|
||||
if (!analysis.isInterface()) {
|
||||
for (ElementDefinition e : analysis.getRootType().getChildren()) {
|
||||
genElementParser(analysis, analysis.getRootType(), e, bUseOwner, null);
|
||||
}
|
||||
}
|
||||
parser.append(" }\r\n\r\n");
|
||||
}
|
||||
|
@ -187,10 +190,11 @@ public class JavaParserJsonGenerator extends JavaBaseGenerator {
|
|||
String prsr = null;
|
||||
String aprsr = null;
|
||||
String anprsr = null;
|
||||
EnumInfo ei = null;
|
||||
String en = null;
|
||||
if (ed.hasUserData("java.enum")) {
|
||||
EnumInfo ei = (EnumInfo) ed.getUserData("java.enum"); // getCodeListType(cd.getBinding());
|
||||
ei = (EnumInfo) ed.getUserData("java.enum"); // getCodeListType(cd.getBinding());
|
||||
ValueSet vs = ei.getValueSet();
|
||||
String en;
|
||||
if (vs.hasUserData("shared")) {
|
||||
en = "Enumerations."+ei.getName();
|
||||
} else {
|
||||
|
@ -238,7 +242,16 @@ public class JavaParserJsonGenerator extends JavaBaseGenerator {
|
|||
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(" if (array.get(i).isJsonNull()) {\r\n");
|
||||
if (en == null) {
|
||||
parser.append(" res.get"+upFirst(name)+"().add(new "+tn+"Type());\r\n");
|
||||
} else {
|
||||
parser.append(" res.get"+upFirst(name)+"().add(new Enumeration<"+en+">(new "+en+"EnumFactory(), "+en+".NULL));\r\n");
|
||||
}
|
||||
|
||||
parser.append(" } else {;\r\n");
|
||||
parser.append(" res.get"+upFirst(name)+"().add("+aprsr+");\r\n");
|
||||
parser.append(" }\r\n");
|
||||
parser.append(" }\r\n");
|
||||
parser.append(" };\r\n");
|
||||
parser.append(" if (json.has(\"_"+name+"\")) {\r\n");
|
||||
|
@ -300,8 +313,10 @@ public class JavaParserJsonGenerator extends JavaBaseGenerator {
|
|||
|
||||
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);
|
||||
if (!analysis.isInterface()) {
|
||||
for (ElementDefinition e : analysis.getRootType().getChildren()) {
|
||||
genElementComposer(analysis, analysis.getRootType(), e, null);
|
||||
}
|
||||
}
|
||||
composer.append(" }\r\n\r\n");
|
||||
}
|
||||
|
|
|
@ -175,10 +175,12 @@ public class JavaParserXmlGenerator extends JavaBaseGenerator {
|
|||
String tn = ti.getName();
|
||||
parser.append(" protected boolean parse"+upFirst(tn).replace(".", "")+"Content(int eventType, XmlPullParser xpp, "+tn+" res) throws XmlPullParserException, IOException, FHIRFormatError {\r\n");
|
||||
boolean first = true;
|
||||
for (ElementDefinition ed : ti.getChildren()) {
|
||||
if (!ed.hasRepresentation(PropertyRepresentation.XMLATTR)) {
|
||||
genElement(analysis, ti, ed, null, first);
|
||||
first = false;
|
||||
if (!analysis.isInterface()) {
|
||||
for (ElementDefinition ed : ti.getChildren()) {
|
||||
if (!ed.hasRepresentation(PropertyRepresentation.XMLATTR)) {
|
||||
genElement(analysis, ti, ed, null, first);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!first)
|
||||
|
@ -279,6 +281,13 @@ public class JavaParserXmlGenerator extends JavaBaseGenerator {
|
|||
} else {
|
||||
composer.append(" composeElementAttributes(element);\r\n");
|
||||
}
|
||||
for (ElementDefinition ed : ti.getChildren()) {
|
||||
if (ed.hasRepresentation(PropertyRepresentation.XMLATTR)) {
|
||||
composer.append(" if (element.has"+upFirst(getElementName(ed.getName(), true))+"Element())\r\n");
|
||||
composer.append(" xml.attribute(\""+ed.getName()+"\", element.get"+upFirst(getElementName(ed.getName(), true))+"Element().getValue());\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
composer.append(" xml.enter(FHIR_NS, name);\r\n");
|
||||
composer.append(" compose"+pfx+tn+"Elements(element);\r\n");
|
||||
composer.append(" composeElementClose(element);\r\n");
|
||||
|
@ -302,10 +311,12 @@ public class JavaParserXmlGenerator extends JavaBaseGenerator {
|
|||
|
||||
composer.append(" protected void compose"+tn+"Elements("+tn+" element) throws IOException {\r\n");
|
||||
composer.append(" compose"+ti.getAncestorName()+"Elements(element);\r\n");
|
||||
|
||||
for (ElementDefinition ed : ti.getChildren()) {
|
||||
if (!ed.hasRepresentation(PropertyRepresentation.XMLATTR)) {
|
||||
genElementCompose(analysis, ti, ed, null);
|
||||
|
||||
if (!analysis.isInterface()) {
|
||||
for (ElementDefinition ed : ti.getChildren()) {
|
||||
if (!ed.hasRepresentation(PropertyRepresentation.XMLATTR)) {
|
||||
genElementCompose(analysis, ti, ed, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
composer.append(" }\r\n\r\n");
|
||||
|
|
|
@ -1858,16 +1858,24 @@ private void generatePropertyMaker(Analysis analysis, TypeInfo ti, String indent
|
|||
* getXXXFirstRep() for repeatable element
|
||||
*/
|
||||
if (!"DomainResource".equals(className)) {
|
||||
jdoc(indent, "@return The first repetition of repeating field {@link #"+getElementName(e.getName(), true)+"}, creating it if it does not already exist");
|
||||
jdoc(indent, "@return The first repetition of repeating field {@link #"+getElementName(e.getName(), true)+"}, creating it if it does not already exist {3}");
|
||||
write(indent+"public "+tn+" get"+getTitle(getElementName(e.getName(), false))+"FirstRep() { \r\n");
|
||||
write(indent+" if (get"+getTitle(getElementName(e.getName(), false))+"().isEmpty()) {\r\n");
|
||||
if (e.unbounded()) {
|
||||
write(indent+" if (get"+getTitle(getElementName(e.getName(), false))+"().isEmpty()) {\r\n");
|
||||
} else {
|
||||
write(indent+" if ("+getElementName(e.getName(), false)+" == null) {\r\n");
|
||||
}
|
||||
if ((definitions.hasPrimitiveType(e.typeSummary()))) {
|
||||
write(indent+" add" + getTitle(getElementName(e.getName(), false)) + "Element();\r\n");
|
||||
} else {
|
||||
write(indent+" add" + getTitle(getElementName(e.getName(), false)) + "();\r\n");
|
||||
}
|
||||
write(indent+" }\r\n");
|
||||
write(indent+" return get"+getTitle(getElementName(e.getName(), false))+"().get(0);\r\n");
|
||||
if (e.unbounded()) {
|
||||
write(indent+" return get"+getTitle(getElementName(e.getName(), false))+"().get(0);\r\n");
|
||||
} else {
|
||||
write(indent+" return "+getElementName(e.getName(), false)+";\r\n");
|
||||
}
|
||||
write(indent+"}\r\n\r\n");
|
||||
}
|
||||
|
||||
|
@ -2087,7 +2095,7 @@ private void generatePropertyMaker(Analysis analysis, TypeInfo ti, String indent
|
|||
* getXXXFirstRep() for repeatable element
|
||||
*/
|
||||
if (!"DomainResource".equals(ti.getName())) {
|
||||
jdoc(indent, "@return The first repetition of repeating field {@link #"+getElementName(e.getName(), true)+"}, creating it if it does not already exist");
|
||||
jdoc(indent, "@return The first repetition of repeating field {@link #"+getElementName(e.getName(), true)+"}, creating it if it does not already exist {1}");
|
||||
write(indent+"public abstract "+tn+" get"+getTitle(getElementName(e.getName(), false))+"FirstRep(); \r\n");
|
||||
}
|
||||
}
|
||||
|
@ -2272,7 +2280,7 @@ private void generatePropertyMaker(Analysis analysis, TypeInfo ti, String indent
|
|||
* getXXXFirstRep() for repeatable element
|
||||
*/
|
||||
if (!"DomainResource".equals(className)) {
|
||||
jdoc(indent, "@return The first repetition of repeating field {@link #"+getElementName(e.getName(), true)+"}, creating it if it does not already exist");
|
||||
jdoc(indent, "@return The first repetition of repeating field {@link #"+getElementName(e.getName(), true)+"}, creating it if it does not already exist {2}");
|
||||
write(indent+"public "+tn+" get"+getTitle(getElementName(e.getName(), false))+"FirstRep() { \r\n");
|
||||
write(indent+" throw new Error(\"The resource type \\\""+analysis.getName()+"\\\" does not implement the property \\\""+e.getName()+"\\\"\");\r\n");
|
||||
write(indent+"}\r\n");
|
||||
|
|
|
@ -58,7 +58,7 @@ public class JavaCoreGenerator {
|
|||
long start = System.currentTimeMillis();
|
||||
Date date = new Date();
|
||||
|
||||
String ap = Utilities.path(src, "src", "main", "resources");
|
||||
String ap = Utilities.path(src);
|
||||
System.out.println("Load Configuration from "+ap);
|
||||
Configuration config = new Configuration(ap);
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package org.hl7.fhir.core.generator.tests;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.xml.XMLUtil;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class RoundTripTests {
|
||||
private static final String EXAMPLES_DIR = "R:\\fhir\\publish\\examples";
|
||||
|
||||
@Parameters(name = "{index}: file {0}")
|
||||
public static Iterable<Object[]> data() throws ParserConfigurationException, SAXException, IOException {
|
||||
File dir = new File(EXAMPLES_DIR);
|
||||
|
||||
String[] list = dir.list();
|
||||
List<Object[]> objects = new ArrayList<Object[]>(list.length);
|
||||
|
||||
for (String s : list) {
|
||||
objects.add(new Object[] { s, s });
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
private String name;
|
||||
|
||||
public RoundTripTests(String name, String unused) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws FileNotFoundException, IOException {
|
||||
byte[] src = TextFile.fileToBytes(Utilities.path(EXAMPLES_DIR, name));
|
||||
Resource r = new XmlParser().parse(src);
|
||||
assertNotNull(r);
|
||||
byte[] cnt = new XmlParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(r);
|
||||
Utilities.createDirectory(output());
|
||||
save(src, Utilities.path(output(), r.fhirType()+"-"+r.getId()+".src.xml"));
|
||||
save(cnt, Utilities.path(output(), r.fhirType()+"-"+r.getId()+".cnt.xml"));
|
||||
cnt = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeBytes(r);
|
||||
save(cnt, Utilities.path(output(), r.fhirType()+"-"+r.getId()+".cnt.json"));
|
||||
Resource rj = new JsonParser().parse(cnt);
|
||||
assertNotNull(rj);
|
||||
if (r instanceof DomainResource) {
|
||||
((DomainResource) r).setText(null);
|
||||
}
|
||||
if (rj instanceof DomainResource) {
|
||||
((DomainResource) rj).setText(null);
|
||||
}
|
||||
assertTrue(r.equalsDeep(rj));
|
||||
}
|
||||
|
||||
private String output() throws IOException {
|
||||
return Utilities.path("[tmp]", "round-trip");
|
||||
}
|
||||
|
||||
private void save(byte[] src, String path) throws IOException {
|
||||
File f = new File(path);
|
||||
if (f.exists()) {
|
||||
f.delete();
|
||||
}
|
||||
TextFile.bytesToFile(src, f);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue