generate resource related files using external templates

This commit is contained in:
bdenton 2016-03-24 10:34:54 -07:00
parent 1adfc4b4d9
commit 42a9bac809
12 changed files with 551 additions and 3 deletions

View File

@ -99,6 +99,7 @@ tmp/
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
@ -114,6 +115,7 @@ local.properties
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath

View File

@ -0,0 +1,158 @@
package ca.uhn.fhir.tinder;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.TreeSet;
import org.apache.http.ParseException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet;
@Mojo(name = "generate-multi-files", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class TinderGenericMultiFileMojo extends AbstractMojo {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TinderGenericMultiFileMojo.class);
// one of these two is required
@Parameter(required = false)
private String template;
@Parameter(required = false)
private File templateFile;
@Parameter(required = true, defaultValue = "ResourceProvider")
private String filenameSuffix;
@Parameter(required = true, defaultValue = "${project.build.directory}/generated-sources/tinder")
private File targetDirectory;
@Parameter(required = true)
private String packageBase;
@Parameter(required = false)
private List<String> baseResourceNames;
@Parameter(required = false)
private List<String> excludeResourceNames;
@Parameter(required = true, defaultValue = "${project.build.directory}/..")
private String baseDir;
@Parameter(required = true)
private String version;
@Component
private MavenProject myProject;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
FhirContext fhirContext;
if ("dstu".equals(version)) {
fhirContext = FhirContext.forDstu1();
} else if ("dstu2".equals(version)) {
fhirContext = FhirContext.forDstu2();
} else if ("dstu3".equals(version)) {
fhirContext = FhirContext.forDstu3();
} else {
throw new MojoFailureException("Unknown version configured: " + version);
}
if (baseResourceNames == null || baseResourceNames.isEmpty()) {
baseResourceNames = new ArrayList<String>();
ourLog.info("No resource names supplied, going to use all resources from version: {}",fhirContext.getVersion().getVersion());
Properties p = new Properties();
try {
p.load(fhirContext.getVersion().getFhirVersionPropertiesFile());
} catch (IOException e) {
throw new MojoFailureException("Failed to load version property file", e);
}
ourLog.debug("Property file contains: {}",p);
TreeSet<String> keys = new TreeSet<String>();
for(Object next : p.keySet()) {
keys.add((String) next);
}
for (String next : keys) {
if (next.startsWith("resource.")) {
baseResourceNames.add(next.substring("resource.".length()).toLowerCase());
}
}
}
for (int i = 0; i < baseResourceNames.size(); i++) {
baseResourceNames.set(i, baseResourceNames.get(i).toLowerCase());
}
if (excludeResourceNames != null) {
for (int i = 0; i < excludeResourceNames.size(); i++) {
excludeResourceNames.set(i, excludeResourceNames.get(i).toLowerCase());
}
baseResourceNames.removeAll(excludeResourceNames);
}
ourLog.info("Including the following resources: {}", baseResourceNames);
File packageDirectoryBase = new File(targetDirectory, packageBase.replace(".", File.separatorChar + ""));
packageDirectoryBase.mkdirs();
ResourceGeneratorUsingSpreadsheet gen = new ResourceGeneratorUsingSpreadsheet(version, baseDir);
gen.setBaseResourceNames(baseResourceNames);
try {
gen.parse();
gen.setFilenameSuffix(filenameSuffix);
gen.setTemplate(template);
gen.setTemplateFile(templateFile);
gen.writeAll(packageDirectoryBase, null,packageBase);
} catch (Exception e) {
throw new MojoFailureException("Failed to generate files", e);
}
myProject.addCompileSourceRoot(targetDirectory.getAbsolutePath());
}
public static void main(String[] args) throws ParseException, IOException, MojoFailureException, MojoExecutionException {
// PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
// HttpClientBuilder builder = HttpClientBuilder.create();
// builder.setConnectionManager(connectionManager);
// CloseableHttpClient client = builder.build();
//
// HttpGet get = new HttpGet("http://fhir.healthintersections.com.au/open/metadata");
// CloseableHttpResponse response = client.execute(get);
//
// String metadataString = EntityUtils.toString(response.getEntity());
//
// ourLog.info("Metadata String: {}", metadataString);
// String metadataString = IOUtils.toString(new FileInputStream("src/test/resources/healthintersections-metadata.xml"));
// Conformance conformance = new FhirContext(Conformance.class).newXmlParser().parseResource(Conformance.class, metadataString);
TinderGenericMultiFileMojo mojo = new TinderGenericMultiFileMojo();
mojo.myProject = new MavenProject();
mojo.version = "dstu2";
mojo.packageBase = "ca.uhn.test";
mojo.template = "/vm/jpa_resource_provider.vm";
mojo.targetDirectory = new File("target/generated/valuesets");
mojo.execute();
}
}

View File

@ -0,0 +1,226 @@
package ca.uhn.fhir.tinder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.TreeSet;
import org.apache.commons.lang.WordUtils;
import org.apache.http.ParseException;
import org.apache.maven.model.FileSet;
import org.apache.maven.model.PatternSet;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.generic.EscapeTool;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.tinder.parser.BaseStructureSpreadsheetParser;
import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet;
@Mojo(name = "generate-single-file", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class TinderGenericSingleFileMojo extends AbstractMojo {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TinderGenericSingleFileMojo.class);
// one of these two is required
@Parameter(required = false)
private String template;
@Parameter(required = false)
private File templateFile;
@Parameter(required = true, defaultValue = "${project.build.directory}/generated-sources/tinder")
private File targetDirectory;
@Parameter(required = false)
private String targetFolder;
@Parameter(required = false)
private String targetPackage;
@Parameter(required = true)
private String targetFile;
@Parameter(required = true)
private String packageBase;
@Parameter(required = false)
private List<String> baseResourceNames;
@Parameter(required = false)
private List<String> excludeResourceNames;
@Parameter(required = true, defaultValue = "${project.build.directory}/..")
private String baseDir;
@Parameter(required = true)
private String version;
@Component
private MavenProject myProject;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
FhirContext fhirContext;
if ("dstu".equals(version)) {
fhirContext = FhirContext.forDstu1();
} else if ("dstu2".equals(version)) {
fhirContext = FhirContext.forDstu2();
} else if ("dstu3".equals(version)) {
fhirContext = FhirContext.forDstu3();
} else {
throw new MojoFailureException("Unknown version configured: " + version);
}
if (baseResourceNames == null || baseResourceNames.isEmpty()) {
baseResourceNames = new ArrayList<String>();
ourLog.info("No resource names supplied, going to use all resources from version: {}",fhirContext.getVersion().getVersion());
Properties p = new Properties();
try {
p.load(fhirContext.getVersion().getFhirVersionPropertiesFile());
} catch (IOException e) {
throw new MojoFailureException("Failed to load version property file", e);
}
ourLog.debug("Property file contains: {}",p);
TreeSet<String> keys = new TreeSet<String>();
for(Object next : p.keySet()) {
keys.add((String) next);
}
for (String next : keys) {
if (next.startsWith("resource.")) {
baseResourceNames.add(next.substring("resource.".length()).toLowerCase());
}
}
}
for (int i = 0; i < baseResourceNames.size(); i++) {
baseResourceNames.set(i, baseResourceNames.get(i).toLowerCase());
}
if (excludeResourceNames != null) {
for (int i = 0; i < excludeResourceNames.size(); i++) {
excludeResourceNames.set(i, excludeResourceNames.get(i).toLowerCase());
}
baseResourceNames.removeAll(excludeResourceNames);
}
ourLog.info("Including the following resources: {}", baseResourceNames);
ResourceGeneratorUsingSpreadsheet gen = new ResourceGeneratorUsingSpreadsheet(version, baseDir);
gen.setBaseResourceNames(baseResourceNames);
try {
gen.parse();
VelocityContext ctx = new VelocityContext();
ctx.put("resources", gen.getResources());
ctx.put("packageBase", packageBase);
ctx.put("targetPackage", targetPackage);
ctx.put("version", version);
ctx.put("esc", new EscapeTool());
if (BaseStructureSpreadsheetParser.determineVersionEnum(version).isRi()) {
ctx.put("resourcePackage", "org.hl7.fhir." + version + ".model");
} else {
ctx.put("resourcePackage", "ca.uhn.fhir.model." + version + ".resource");
}
String capitalize = WordUtils.capitalize(version);
if ("Dstu".equals(capitalize)) {
capitalize="Dstu1";
}
ctx.put("versionCapitalized", capitalize);
VelocityEngine v = new VelocityEngine();
v.setProperty("resource.loader", "cp");
v.setProperty("cp.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
v.setProperty("runtime.references.strict", Boolean.TRUE);
InputStream templateIs = null;
if (templateFile != null) {
templateIs = new FileInputStream(templateFile);
} else {
templateIs = ResourceGeneratorUsingSpreadsheet.class.getResourceAsStream(template);
}
InputStreamReader templateReader = new InputStreamReader(templateIs);
File target = targetDirectory;
if (targetFolder != null) {
targetFolder = targetFolder.replace('\\', '/');
targetFolder = targetFolder.replace('/', File.separatorChar);
target = new File(targetDirectory, targetFolder);
} else if (targetPackage != null) {
target = new File(targetDirectory, targetPackage.replace('.', File.separatorChar));
}
target.mkdirs();
File f = new File(target, targetFile);
OutputStreamWriter w = new OutputStreamWriter(new FileOutputStream(f, false), "UTF-8");
v.evaluate(ctx, w, "", templateReader);
w.close();
if (targetFile.endsWith(".java")) {
myProject.addCompileSourceRoot(targetDirectory.getAbsolutePath());
} else {
Resource resource = new Resource();
resource.setDirectory(targetDirectory.getAbsolutePath());
String resName = targetFile;
if (targetFolder != null) {
resName = targetFolder+File.separator+targetFile;
}
resource.addInclude(resName);
myProject.addResource(resource);
}
} catch (Exception e) {
throw new MojoFailureException("Failed to generate file", e);
}
}
public static void main(String[] args) throws ParseException, IOException, MojoFailureException, MojoExecutionException {
// PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
// HttpClientBuilder builder = HttpClientBuilder.create();
// builder.setConnectionManager(connectionManager);
// CloseableHttpClient client = builder.build();
//
// HttpGet get = new HttpGet("http://fhir.healthintersections.com.au/open/metadata");
// CloseableHttpResponse response = client.execute(get);
//
// String metadataString = EntityUtils.toString(response.getEntity());
//
// ourLog.info("Metadata String: {}", metadataString);
// String metadataString = IOUtils.toString(new FileInputStream("src/test/resources/healthintersections-metadata.xml"));
// Conformance conformance = new FhirContext(Conformance.class).newXmlParser().parseResource(Conformance.class, metadataString);
TinderGenericSingleFileMojo mojo = new TinderGenericSingleFileMojo();
mojo.myProject = new MavenProject();
mojo.template = "/vm/jpa_spring_beans.vm";
mojo.version = "dstu2";
mojo.packageBase = "ca.uhn.test";
mojo.targetDirectory = new File("target/generated/valuesets");
mojo.targetFile = "tmp_beans.xml";
mojo.execute();
}
}

View File

@ -4,6 +4,7 @@ import static org.apache.commons.lang.StringUtils.defaultString;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@ -172,6 +173,8 @@ public abstract class BaseStructureParser {
}
protected abstract String getTemplate();
protected abstract File getTemplateFile();
protected boolean isSpreadsheet(String theFileName) {
return true;
@ -480,7 +483,10 @@ public abstract class BaseStructureParser {
v.setProperty("cp.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
v.setProperty("runtime.references.strict", Boolean.TRUE);
InputStream templateIs = ResourceGeneratorUsingSpreadsheet.class.getResourceAsStream(getTemplate());
InputStream templateIs =
getTemplateFile() != null
? new FileInputStream(getTemplateFile())
: ResourceGeneratorUsingSpreadsheet.class.getResourceAsStream(getTemplate());
InputStreamReader templateReader = new InputStreamReader(templateIs);
v.evaluate(ctx, w, "", templateReader);
@ -524,7 +530,14 @@ public abstract class BaseStructureParser {
// File f = new File(theOutputDirectory, (next.getDeclaringClassNameComplete()) /*+ getFilenameSuffix()*/ +
// ".java");
String elementName = Resource.correctName(next.getElementName());
File f = new File(theOutputDirectory, elementName + getFilenameSuffix() + ".java");
String fwork = getFilenameSuffix();
// TODO -- how to generate multiple non-Java files??
if (fwork.endsWith(".java")) {
fwork = elementName + fwork;
} else {
fwork = elementName + fwork + ".java";
}
File f = new File(theOutputDirectory, fwork);
try {
write(next, f, thePackageBase);
} catch (IOException e) {

View File

@ -40,6 +40,11 @@ public class DatatypeGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
protected String getTemplate() {
return "dstu".equals(getVersion()) ? "/vm/dt_composite_dstu.vm" : "/vm/dt_composite.vm";
}
@Override
protected File getTemplateFile() {
return null;
}
@Override
protected String getFilenameSuffix() {

View File

@ -62,6 +62,11 @@ public class ProfileParser extends BaseStructureParser {
protected String getTemplate() {
return "dstu".equals(getVersion()) ? "/vm/resource_dstu.vm" : "/vm/resource.vm";
}
@Override
protected File getTemplateFile() {
return null;
}
public void parseSingleProfile(File theProfile, String theHttpUrl) throws MojoFailureException {
String profileString;

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.tinder.parser;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
@ -16,6 +17,7 @@ public class ResourceGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
private List<String> myInputStreamNames;
private ArrayList<InputStream> myInputStreams;
private String myTemplate = null;
private File myTemplateFile = null;
public ResourceGeneratorUsingSpreadsheet(String theVersion, String theBaseDir) {
super(theVersion, theBaseDir);
@ -74,6 +76,10 @@ public class ResourceGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
myTemplate = theTemplate;
}
public void setTemplateFile (File theTemplateFile) {
myTemplateFile = theTemplateFile;
}
@Override
protected BaseRootType createRootType() {
return new Resource();
@ -100,6 +106,11 @@ public class ResourceGeneratorUsingSpreadsheet extends BaseStructureSpreadsheetP
}
}
@Override
protected File getTemplateFile() {
return myTemplateFile;
}
@Override
protected boolean isSpreadsheet(String theFileName) {
return theFileName.endsWith("spreadsheet.xml");

View File

@ -97,7 +97,42 @@
<buildDatatypes>true</buildDatatypes>
</configuration>
</execution>
<!-- <execution> <id>client</id> <goals> <goal>generate-client</goal> </goals> <configuration> <clientClassName>ca.uhn.hitest.HiTest</clientClassName> <serverBaseHref>http://fhir.healthintersections.com.au/open</serverBaseHref>
<execution>
<id>generic_multi</id>
<goals>
<goal>generate-multi-files</goal>
</goals>
<configuration>
<version>dstu</version>
<templateFile>${project.basedir}/src/test/resources/templates/resource_test.vm</templateFile>
<packageBase>ca.uhn.test.generic.multi</packageBase>
<targetDirectory>${project.build.directory}/generated-sources/tinder</targetDirectory>
<filenameSuffix>ResourceTest.java</filenameSuffix>
<baseResourceNames>
<baseResourceName>patient</baseResourceName>
<baseResourceName>organization</baseResourceName>
</baseResourceNames>
</configuration>
</execution>
<execution>
<id>generic_single</id>
<goals>
<goal>generate-single-file</goal>
</goals>
<configuration>
<version>dstu</version>
<templateFile>${project.basedir}/src/test/resources/templates/resource_test_beans_java.vm</templateFile>
<packageBase>ca.uhn.test.generic.multi</packageBase>
<targetDirectory>${project.build.directory}/generated-sources/tinder</targetDirectory>
<targetPackage>ca.uhn.test.generic.single</targetPackage>
<targetFile>TestConfigDstu1.java</targetFile>
<baseResourceNames>
<baseResourceName>patient</baseResourceName>
<baseResourceName>organization</baseResourceName>
</baseResourceNames>
</configuration>
</execution>
<!-- <execution> <id>client</id> <goals> <goal>generate-client</goal> </goals> <configuration> <clientClassName>ca.uhn.hitest.HiTest</clientClassName> <serverBaseHref>http://fhir.healthintersections.com.au/open</serverBaseHref>
<generateSearchForAllParams>true</generateSearchForAllParams> </configuration> </execution> -->
</executions>
<dependencies>
@ -139,6 +174,32 @@
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-tinder-plugin</artifactId>
<versionRange>[0.4-SNAPSHOT,)</versionRange>
<goals>
<goal>generate-multi-files</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-tinder-plugin</artifactId>
<versionRange>[0.4-SNAPSHOT,)</versionRange>
<goals>
<goal>generate-single-file</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>

View File

@ -0,0 +1,5 @@
package test;
public interface ResourceTest {
String getResourceName();
}

View File

@ -0,0 +1,23 @@
package test;
import java.util.List;
import org.junit.Test;
import ca.uhn.test.generic.single.TestConfigDstu1;
import ca.uhn.test.generic.multi.*;
import test.ResourceTest;
public class TestGenerics {
@Test
public void testGeneratedListReferencingGenerics() {
// This won't compile if tinder didn't generate the right names...
TestConfigDstu1 config = new TestConfigDstu1();
List<ResourceTest> generics = config.testProvidersDstu1();
for (ResourceTest generic : generics) {
String name = generic.getResourceName();
}
}
}

View File

@ -0,0 +1,13 @@
package ${packageBase};
import java.util.*;
import test.ResourceTest;
public class ${className}ResourceTest implements ResourceTest {
public String getResourceName() {
return "${className}";
}
}

View File

@ -0,0 +1,26 @@
package ${targetPackage};
import java.util.ArrayList;
import java.util.List;
import test.ResourceTest;
public class TestConfig${versionCapitalized} {
public List<ResourceTest> testProviders${versionCapitalized}() {
List<ResourceTest> result = new ArrayList<test.ResourceTest>();
#foreach ( $res in $resources )
result.add(test${res.declaringClassNameComplete}${versionCapitalized}());
#end
return result;
}
#foreach ( $res in $resources )
public ${packageBase}.${res.declaringClassNameComplete}ResourceTest test${res.declaringClassNameComplete}${versionCapitalized}() {
${packageBase}.${res.declaringClassNameComplete}ResourceTest result;
result = new ${packageBase}.${res.declaringClassNameComplete}ResourceTest();
return result;
}
#end
}