package ca.uhn.fhir.tinder; import java.io.File; 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 org.apache.commons.lang3.StringUtils; 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.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; 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.model.dstu.resource.Conformance; import ca.uhn.fhir.model.dstu.resource.Conformance.Rest; import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource; import ca.uhn.fhir.model.dstu.resource.Profile; import ca.uhn.fhir.model.dstu.valueset.RestfulConformanceModeEnum; import ca.uhn.fhir.rest.client.api.IBasicClient; import ca.uhn.fhir.tinder.model.BaseRootType; import ca.uhn.fhir.tinder.model.RestResourceTm; import ca.uhn.fhir.tinder.model.SearchParameter; import ca.uhn.fhir.tinder.parser.ProfileParser; import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet; @Mojo(name = "generate-client", defaultPhase = LifecyclePhase.GENERATE_SOURCES) public class TinderClientMojo extends AbstractMojo { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TinderClientMojo.class); @Parameter(required = true) private String serverBaseHref; @Parameter(required = true) private String clientClassName; @Parameter(required = true, defaultValue = "${project.build.directory}/generated-sources/tinder") private File targetDirectory; @Parameter(required = true, defaultValue = "false") private boolean generateSearchForAllParams; @Parameter(alias = "version", required = true, defaultValue="dstu") private String version = "dstu"; @Parameter(required = true, defaultValue = "${project.build.directory}/..") private String baseDir; private List<RestResourceTm> myResources = new ArrayList<RestResourceTm>(); private String myPackageBase; private File myDirectoryBase; private String myClientClassSimpleName; @Override public void execute() throws MojoExecutionException, MojoFailureException { determinePaths(); // // try { // ProfileParser pp = new ProfileParser(); // Profile prof=(Profile) new FhirContext(Profile.class).newXmlParser().parseResource(IOUtils.toString(new FileReader("src/test/resources/profile.xml"))); // pp.parseSingleProfile(prof, "http://foo"); // File resourceDir = new File(myDirectoryBase, "resource"); // resourceDir.mkdirs(); // pp.writeAll(resourceDir, myPackageBase); // } catch (Exception e) { // throw new MojoFailureException("Failed to load resource profile: ",e); // } // if (true) { // return; // } FhirContext ctx = new FhirContext(Conformance.class); IBasicClient client = ctx.newRestfulClient(IBasicClient.class, serverBaseHref); Conformance conformance = (Conformance)client.getServerConformanceStatement(); if (conformance.getRest().size() != 1) { throw new MojoFailureException("Found " + conformance.getRest().size() + " rest definitions in Conformance resource. Need exactly 1."); } Rest rest = conformance.getRest().get(0); if (rest.getMode().getValueAsEnum() != RestfulConformanceModeEnum.SERVER) { throw new MojoFailureException("Conformance mode is not server, found: " + rest.getMode().getValue()); } ProfileParser pp = new ProfileParser(version,baseDir ); for (RestResource nextResource : rest.getResource()) { if (StringUtils.isBlank(nextResource.getProfile().getReference().getValue())) { continue; } RestResourceTm nextTmResource = new RestResourceTm(nextResource); myResources.add(nextTmResource); Profile profile; try { ourLog.info("Loading Profile: {}", nextResource.getProfile().getReference().getValue()); profile = (Profile) nextResource.getProfile().loadResource(client); } catch (Exception e) { throw new MojoFailureException("Failed to load resource profile: " + nextResource.getProfile().getReference().getValue(), e); } BaseRootType resourceModel; try { resourceModel = pp.parseSingleProfile(profile, nextResource.getProfile().getReference().getValue()); } catch (Exception e) { throw new MojoFailureException("Failed to load resource profile: " + nextResource.getProfile().getReference().getValue(), e); } if (generateSearchForAllParams) { for (SearchParameter next : resourceModel.getSearchParameters()) { nextTmResource.getSearchParams().add(next); } } } File resourceDir = new File(myDirectoryBase, "resource"); resourceDir.mkdirs(); pp.markResourcesForImports(); pp.writeAll(resourceDir, null,myPackageBase); try { write(); } catch (IOException e) { throw new MojoFailureException("Failed to write", e); } } private void determinePaths() { myPackageBase = ""; myDirectoryBase = targetDirectory; myClientClassSimpleName = clientClassName; if (clientClassName.lastIndexOf('.') > -1) { myPackageBase = clientClassName.substring(0, clientClassName.lastIndexOf('.')); myDirectoryBase = new File(myDirectoryBase, myPackageBase.replace(".", File.separatorChar + "")); myClientClassSimpleName = clientClassName.substring(clientClassName.lastIndexOf('.') + 1); } myDirectoryBase.mkdirs(); } private void write() throws IOException { File file = new File(myDirectoryBase, myClientClassSimpleName + ".java"); OutputStreamWriter w = new OutputStreamWriter(new FileOutputStream(file, false), "UTF-8"); ourLog.debug("Writing file: {}", file.getAbsolutePath()); VelocityContext ctx = new VelocityContext(); ctx.put("packageBase", myPackageBase); ctx.put("className", myClientClassSimpleName); ctx.put("resources", myResources); ctx.put("esc", new EscapeTool()); 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 = ResourceGeneratorUsingSpreadsheet.class.getResourceAsStream("/vm/client.vm"); InputStreamReader templateReader = new InputStreamReader(templateIs); v.evaluate(ctx, w, "", templateReader); w.close(); } 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); TinderClientMojo mojo = new TinderClientMojo(); mojo.clientClassName = "ca.uhn.test.ClientClass"; mojo.targetDirectory = new File("target/gen"); mojo.serverBaseHref = "http://fhir.healthintersections.com.au/open"; mojo.generateSearchForAllParams = true; mojo.execute(); } }