package ca.uhn.fhir.tinder;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
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.tinder.parser.DatatypeGeneratorUsingSpreadsheet;
import ca.uhn.fhir.tinder.parser.ProfileParser;
import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet;
@Mojo(name = "generate-structures", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class TinderStructuresMojo extends AbstractMojo {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TinderStructuresMojo.class);
@Parameter(required = false)
private List<String> baseResourceNames;
@Parameter(required = false, defaultValue = "false")
private boolean buildDatatypes;
@Component
private MavenProject myProject;
@Parameter(alias = "package", required = true)
private String packageName;
@Parameter(alias = "version", required = true, defaultValue="dstu")
private String version = "dstu";
@Parameter(required = false)
private List<ProfileFileDefinition> resourceProfileFiles;
@Parameter(required = false)
private List<ValueSetFileDefinition> resourceValueSetFiles;
@Parameter(required = true, defaultValue = "${project.build.directory}/generated-sources/tinder")
private String targetDirectory;
@Parameter(required = true, defaultValue = "${project.build.directory}/generated-resources/tinder")
private String targetResourceDirectory;
@Parameter(required = true, defaultValue = "${project.build.directory}/..")
private String baseDir;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (StringUtils.isBlank(packageName)) {
throw new MojoFailureException("Package not specified");
}
if (packageName.contains("..") || packageName.endsWith(".")) {
throw new MojoFailureException("Invalid package specified");
}
ourLog.info("Beginning HAPI-FHIR Tinder Code Generation...");
ourLog.info(" * Output Package: " + packageName);
File resDirectoryBase = new File(new File(targetResourceDirectory), packageName.replace('.', File.separatorChar));
resDirectoryBase.mkdirs();
ourLog.info(" * Output Resource Directory: " + resDirectoryBase.getAbsolutePath());
File directoryBase = new File(new File(targetDirectory), packageName.replace('.', File.separatorChar));
directoryBase.mkdirs();
ourLog.info(" * Output Source Directory: " + directoryBase.getAbsolutePath());
ValueSetGenerator vsp = new ValueSetGenerator(version);
vsp.setResourceValueSetFiles(resourceValueSetFiles);
try {
vsp.parse();
} catch (Exception e) {
throw new MojoFailureException("Failed to load valuesets", e);
}
/*
* A few enums are not found by default because none of the generated classes
* refer to them, but we still want them.
*/
vsp.getClassForValueSetIdAndMarkAsNeeded("NarrativeStatus");
ourLog.info("Loading Datatypes...");
Map<String, String> datatypeLocalImports = new HashMap<String, String>();
DatatypeGeneratorUsingSpreadsheet dtp = new DatatypeGeneratorUsingSpreadsheet(version, baseDir);
if (buildDatatypes) {
try {
dtp.parse();
dtp.markResourcesForImports();
} catch (Exception e) {
throw new MojoFailureException("Failed to load datatypes", e);
}
dtp.bindValueSets(vsp);
datatypeLocalImports = dtp.getLocalImports();
}
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet(version, baseDir);
if (baseResourceNames != null && baseResourceNames.size() > 0) {
ourLog.info("Loading Resources...");
try {
rp.setBaseResourceNames(baseResourceNames);
rp.parse();
rp.markResourcesForImports();
} catch (Exception e) {
throw new MojoFailureException("Failed to load resources", e);
}
rp.bindValueSets(vsp);
rp.getLocalImports().putAll(datatypeLocalImports);
datatypeLocalImports.putAll(rp.getLocalImports());
File resSubDirectoryBase = new File(directoryBase, "resource");
ourLog.info("Writing Resources to directory: {}", resSubDirectoryBase.getAbsolutePath());
rp.combineContentMaps(dtp);
rp.writeAll(resSubDirectoryBase, resDirectoryBase, packageName);
}
ProfileParser pp = new ProfileParser(version, baseDir);
if (resourceProfileFiles != null) {
ourLog.info("Loading profiles...");
for (ProfileFileDefinition next : resourceProfileFiles) {
ourLog.info("Parsing file: {}", next.profileFile);
pp.parseSingleProfile(new File(next.profileFile), next.profileSourceUrl);
}
pp.bindValueSets(vsp);
pp.markResourcesForImports();
pp.getLocalImports().putAll(datatypeLocalImports);
datatypeLocalImports.putAll(pp.getLocalImports());
pp.combineContentMaps(rp);
pp.combineContentMaps(dtp);
pp.writeAll(new File(directoryBase, "resource"), resDirectoryBase, packageName);
}
if (dtp != null) {
ourLog.info("Writing Composite Datatypes...");
dtp.combineContentMaps(pp);
dtp.combineContentMaps(rp);
dtp.writeAll(new File(directoryBase, "composite"), resDirectoryBase, packageName);
}
ourLog.info("Writing ValueSet Enums...");
vsp.writeMarkedValueSets(new File(directoryBase, "valueset"), packageName);
myProject.addCompileSourceRoot(targetDirectory);
}
public List<String> getBaseResourceNames() {
return baseResourceNames;
}
public String getPackageName() {
return packageName;
}
public List<ProfileFileDefinition> getResourceProfileFiles() {
return resourceProfileFiles;
}
public List<ValueSetFileDefinition> getResourceValueSetFiles() {
return resourceValueSetFiles;
}
public String getTargetDirectory() {
return targetDirectory;
}
public boolean isBuildDatatypes() {
return buildDatatypes;
}
public void setBaseResourceNames(List<String> theBaseResourceNames) {
baseResourceNames = theBaseResourceNames;
}
public void setBuildDatatypes(boolean theBuildDatatypes) {
buildDatatypes = theBuildDatatypes;
}
public void setPackageName(String thePackageName) {
packageName = thePackageName;
}
public void setResourceProfileFiles(List<ProfileFileDefinition> theResourceProfileFiles) {
resourceProfileFiles = theResourceProfileFiles;
}
public void setResourceValueSetFiles(List<ValueSetFileDefinition> theResourceValueSetFiles) {
resourceValueSetFiles = theResourceValueSetFiles;
}
public void setTargetDirectory(String theTargetDirectory) {
targetDirectory = theTargetDirectory;
}
public static void main(String[] args) throws Exception {
// ProfileParser pp = new ProfileParser();
// pp.parseSingleProfile(new File("../hapi-tinder-test/src/test/resources/profile/patient.xml"), "http://foo");
ValueSetGenerator vsp = new ValueSetGenerator("dstu2");
// vsp.setResourceValueSetFiles(theResourceValueSetFiles);Directory("src/main/resources/vs/");
vsp.parse();
DatatypeGeneratorUsingSpreadsheet dtp = new DatatypeGeneratorUsingSpreadsheet("dstu2", ".");
dtp.parse();
dtp.markResourcesForImports();
dtp.bindValueSets(vsp);
Map<String, String> datatypeLocalImports = dtp.getLocalImports();
String dtOutputDir = "target/generated-sources/tinder/ca/uhn/fhir/model/dev/composite";
ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet("dstu2", ".");
rp.setBaseResourceNames(Arrays.asList( "appointment"//, "auditevent" , "observation"
// //, "contract"
// "valueset", "organization", "location"
// , "observation", "conformance"
// //, "referralrequest"
// , "patient","practitioner","encounter",
// "organization","location","relatedperson","appointment","slot","order"
// //,"availability"
// ,"device", "valueset"
));
rp.parse();
rp.bindValueSets(vsp);
rp.markResourcesForImports();
rp.bindValueSets(vsp);
String rpOutputDir = "target/generated-sources/tinder/ca/uhn/fhir/model/dev/resource";
String rpSOutputDir = "target/generated-resources/tinder/ca/uhn/fhir/model/dev";
dtp.combineContentMaps(rp);
rp.combineContentMaps(dtp);
rp.getLocalImports().putAll(datatypeLocalImports);
datatypeLocalImports.putAll(rp.getLocalImports());
String vsOutputDir = "target/generated-sources/tinder/ca/uhn/fhir/model/dev/valueset";
vsp.writeMarkedValueSets(new File(vsOutputDir), "ca.uhn.fhir.model.dev");
dtp.writeAll(new File(dtOutputDir), null, "ca.uhn.fhir.model.dev");
rp.writeAll(new File(rpOutputDir), new File(rpSOutputDir), "ca.uhn.fhir.model.dev");
}
public static class ProfileFileDefinition {
@Parameter(required = true)
private String profileFile;
@Parameter(required = true)
private String profileSourceUrl;
}
public static class ValueSetFileDefinition {
@Parameter(required = true)
private String valueSetFile;
public String getValueSetFile() {
return valueSetFile;
}
public void setValueSetFile(String theValueSetFile) {
valueSetFile = theValueSetFile;
}
}
}