diff --git a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/AbstractGenerator.java b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/AbstractGenerator.java index 03a07b0fc26..fbbaa69e989 100644 --- a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/AbstractGenerator.java +++ b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/AbstractGenerator.java @@ -1,187 +1,211 @@ -package ca.uhn.fhir.tinder; -/* - * #%L - * HAPI FHIR Tinder Plug-In - * %% - * Copyright (C) 2014 - 2016 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.context.FhirVersionEnum; -import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; -import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet; - -import java.io.IOException; -import java.util.*; - -public abstract class AbstractGenerator { - - protected abstract void logDebug (String message); - - protected abstract void logInfo (String message); - - public void prepare (GeneratorContext context) throws ExecutionException, FailureException { - - /* - * Deal with the FHIR spec version - */ - FhirContext fhirContext; - String packageSuffix = ""; - if ("dstu2".equals(context.getVersion())) { - fhirContext = FhirContext.forDstu2(); - } else if ("dstu3".equals(context.getVersion())) { - fhirContext = FhirContext.forDstu3(); - packageSuffix = ".dstu3"; - } else { - throw new FailureException("Unknown version configured: " + context.getVersion()); - } - context.setPackageSuffix(packageSuffix); - - /* - * Deal with which resources to process - */ - List includeResources = context.getIncludeResources(); - List excludeResources = context.getExcludeResources(); - - if (includeResources == null || includeResources.isEmpty()) { - includeResources = new ArrayList(); - - logInfo("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 FailureException("Failed to load version property file", e); - } - - logDebug("Property file contains: "+p); - - TreeSet keys = new TreeSet(); - for(Object next : p.keySet()) { - keys.add((String) next); - } - for (String next : keys) { - if (next.startsWith("resource.")) { - includeResources.add(next.substring("resource.".length()).toLowerCase()); - } - } - - if (fhirContext.getVersion().getVersion() == FhirVersionEnum.DSTU3) { - includeResources.remove("conformance"); - } - } - - for (int i = 0; i < includeResources.size(); i++) { - includeResources.set(i, includeResources.get(i).toLowerCase()); - } - - if (excludeResources != null) { - for (int i = 0; i < excludeResources.size(); i++) { - excludeResources.set(i, excludeResources.get(i).toLowerCase()); - } - includeResources.removeAll(excludeResources); - } - context.setIncludeResources(includeResources); - - logInfo("Including the following elements: "+includeResources); - - - /* - * Fill in ValueSet and DataTypes used by the resources - */ - ValueSetGenerator vsp = null; - DatatypeGeneratorUsingSpreadsheet dtp = null; - Map datatypeLocalImports = new HashMap(); - - vsp = new ValueSetGenerator(context.getVersion()); - vsp.setResourceValueSetFiles(context.getValueSetFiles()); - context.setValueSetGenerator(vsp); - try { - vsp.parse(); - } catch (Exception e) { - throw new FailureException("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"); - - logInfo("Loading Datatypes..."); - - dtp = new DatatypeGeneratorUsingSpreadsheet(context.getVersion(), context.getBaseDir()); - context.setDatatypeGenerator(dtp); - try { - dtp.parse(); - dtp.markResourcesForImports(); - } catch (Exception e) { - throw new FailureException("Failed to load datatypes", e); - } - dtp.bindValueSets(vsp); - - datatypeLocalImports = dtp.getLocalImports(); - - /* - * Load the requested resources - */ - ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet(context.getVersion(), context.getBaseDir()); - context.setResourceGenerator(rp); - logInfo("Loading Resources..."); - try { - rp.setBaseResourceNames(includeResources); - rp.parse(); - rp.markResourcesForImports(); - } catch (Exception e) { - throw new FailureException("Failed to load resources", e); - } - - rp.bindValueSets(vsp); - rp.getLocalImports().putAll(datatypeLocalImports); - datatypeLocalImports.putAll(rp.getLocalImports()); - rp.combineContentMaps(dtp); - dtp.combineContentMaps(rp); - - } - - public class FailureException extends Exception { - - public FailureException(String message, Throwable cause) { - super(message, cause); - } - public FailureException(Throwable cause) { - super(cause); - } - - public FailureException(String message) { - super(message); - } - - } - - public class ExecutionException extends Exception { - - public ExecutionException(String message, Throwable cause) { - super(message, cause); - } - - public ExecutionException(String message) { - super(message); - } - - } -} +package ca.uhn.fhir.tinder; +/* + * #%L + * HAPI FHIR Tinder Plug-In + * %% + * Copyright (C) 2014 - 2016 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.tinder.parser.BaseStructureParser; +import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; +import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingModel; +import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet; + +import java.io.IOException; +import java.util.*; + +public abstract class AbstractGenerator { + + protected abstract void logDebug (String message); + + protected abstract void logInfo (String message); + + public void prepare (GeneratorContext context) throws ExecutionException, FailureException { + + /* + * Deal with the FHIR spec version + */ + FhirContext fhirContext; + String packageSuffix = ""; + if ("dstu2".equals(context.getVersion())) { + fhirContext = FhirContext.forDstu2(); + } else if ("dstu3".equals(context.getVersion())) { + fhirContext = FhirContext.forDstu3(); + packageSuffix = ".dstu3"; + } else if ("r4".equals(context.getVersion())) { + fhirContext = FhirContext.forR4(); + packageSuffix = ".r4"; + } else { + throw new FailureException("Unknown version configured: " + context.getVersion()); + } + context.setPackageSuffix(packageSuffix); + + /* + * Deal with which resources to process + */ + List includeResources = context.getIncludeResources(); + List excludeResources = context.getExcludeResources(); + + if (includeResources == null || includeResources.isEmpty()) { + includeResources = new ArrayList(); + + logInfo("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 FailureException("Failed to load version property file", e); + } + + logDebug("Property file contains: "+p); + + TreeSet keys = new TreeSet(); + for(Object next : p.keySet()) { + keys.add((String) next); + } + for (String next : keys) { + if (next.startsWith("resource.")) { + includeResources.add(next.substring("resource.".length()).toLowerCase()); + } + } + + if (fhirContext.getVersion().getVersion() == FhirVersionEnum.DSTU3) { + includeResources.remove("conformance"); + } + } + + for (int i = 0; i < includeResources.size(); i++) { + includeResources.set(i, includeResources.get(i).toLowerCase()); + } + + if (excludeResources != null) { + for (int i = 0; i < excludeResources.size(); i++) { + excludeResources.set(i, excludeResources.get(i).toLowerCase()); + } + includeResources.removeAll(excludeResources); + } + context.setIncludeResources(includeResources); + + logInfo("Including the following elements: "+includeResources); + + + /* + * Fill in ValueSet and DataTypes used by the resources + */ + ValueSetGenerator vsp = null; + DatatypeGeneratorUsingSpreadsheet dtp = null; + Map datatypeLocalImports = new HashMap(); + + vsp = new ValueSetGenerator(context.getVersion()); + vsp.setResourceValueSetFiles(context.getValueSetFiles()); + context.setValueSetGenerator(vsp); + try { + vsp.parse(); + } catch (Exception e) { + throw new FailureException("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"); + + logInfo("Loading Datatypes..."); + + dtp = new DatatypeGeneratorUsingSpreadsheet(context.getVersion(), context.getBaseDir()); + context.setDatatypeGenerator(dtp); + try { + dtp.parse(); + dtp.markResourcesForImports(); + } catch (Exception e) { + throw new FailureException("Failed to load datatypes", e); + } + dtp.bindValueSets(vsp); + + datatypeLocalImports = dtp.getLocalImports(); + + /* + * Load the requested resources + */ + + logInfo("Loading Resources..."); + try { + switch (context.getResourceSource()) { + case SPREADSHEET: { + logInfo("... resource definitions from spreadsheets"); + ResourceGeneratorUsingSpreadsheet rp = new ResourceGeneratorUsingSpreadsheet(context.getVersion(), context.getBaseDir()); + context.setResourceGenerator(rp); + + rp.setBaseResourceNames(includeResources); + rp.parse(); + + rp.markResourcesForImports(); + rp.bindValueSets(vsp); + + rp.getLocalImports().putAll(datatypeLocalImports); + datatypeLocalImports.putAll(rp.getLocalImports()); + + rp.combineContentMaps(dtp); + dtp.combineContentMaps(rp); + break; + } + case MODEL: { + logInfo("... resource definitions from model structures"); + ResourceGeneratorUsingModel rp = new ResourceGeneratorUsingModel(context.getVersion(), context.getBaseDir()); + context.setResourceGenerator(rp); + + rp.setBaseResourceNames(includeResources); + rp.parse(); + break; + } + } + } catch (Exception e) { + throw new FailureException("Failed to load resources", e); + } + + } + + public static class FailureException extends Exception { + + public FailureException(String message, Throwable cause) { + super(message, cause); + } + public FailureException(Throwable cause) { + super(cause); + } + + public FailureException(String message) { + super(message); + } + + } + + public static class ExecutionException extends Exception { + + public ExecutionException(String message, Throwable cause) { + super(message, cause); + } + + public ExecutionException(String message) { + super(message); + } + + } +} diff --git a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/GeneratorContext.java b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/GeneratorContext.java index a3b1621d0f4..5d4a2bd9b77 100644 --- a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/GeneratorContext.java +++ b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/GeneratorContext.java @@ -1,137 +1,169 @@ -package ca.uhn.fhir.tinder; -/* - * #%L - * HAPI FHIR Tinder Plug-In - * %% - * Copyright (C) 2014 - 2016 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import ca.uhn.fhir.tinder.TinderStructuresMojo.ValueSetFileDefinition; -import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; -import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet; -import org.apache.maven.plugins.annotations.Parameter; - -import java.util.List; - -/** - * @author Bill.Denton - * - */ -public class GeneratorContext { - private String version; - private String packageSuffix; - private String baseDir; - private List includeResources; - private List excludeResources; - private List valueSetFiles; - private ResourceGeneratorUsingSpreadsheet resourceGenerator = null; - private ValueSetGenerator valueSetGenerator = null; - private DatatypeGeneratorUsingSpreadsheet datatypeGenerator = null; - - public String getBaseDir() { - return baseDir; - } - - public void setBaseDir(String baseDir) { - this.baseDir = baseDir; - } - - public DatatypeGeneratorUsingSpreadsheet getDatatypeGenerator() { - return datatypeGenerator; - } - - public void setDatatypeGenerator(DatatypeGeneratorUsingSpreadsheet datatypeGenerator) { - this.datatypeGenerator = datatypeGenerator; - } - - public List getExcludeResources() { - return excludeResources; - } - - public void setExcludeResources(List excludeResources) { - this.excludeResources = excludeResources; - } - - public List getIncludeResources() { - return includeResources; - } - public void setIncludeResources(List includeResources) { - this.includeResources = includeResources; - } - - public String getPackageSuffix() { - return packageSuffix; - } - - public void setPackageSuffix(String packageSuffix) { - this.packageSuffix = packageSuffix; - } - - public ResourceGeneratorUsingSpreadsheet getResourceGenerator() { - return resourceGenerator; - } - - public void setResourceGenerator(ResourceGeneratorUsingSpreadsheet resourceGenerator) { - this.resourceGenerator = resourceGenerator; - } - - public List getValueSetFiles() { - return valueSetFiles; - } - - public void setValueSetFiles(List valueSetFiles) { - this.valueSetFiles = valueSetFiles; - } - - public ValueSetGenerator getValueSetGenerator() { - return valueSetGenerator; - } - public void setValueSetGenerator(ValueSetGenerator valueSetGenerator) { - this.valueSetGenerator = valueSetGenerator; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public static class ProfileFileDefinition { - @Parameter(required = true) - String profileFile; - - @Parameter(required = true) - String profileSourceUrl; - - public String getProfileFile() { - return profileFile; - } - - public void setProfileFile(String profileFile) { - this.profileFile = profileFile; - } - - public String getProfileSourceUrl() { - return profileSourceUrl; - } - - public void setProfileSourceUrl(String profileSourceUrl) { - this.profileSourceUrl = profileSourceUrl; - } - } -} +package ca.uhn.fhir.tinder; +/* + * #%L + * HAPI FHIR Tinder Plug-In + * %% + * Copyright (C) 2014 - 2016 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import java.util.List; + +import javax.security.auth.login.FailedLoginException; + +import org.apache.commons.lang3.StringUtils; +import org.apache.maven.plugins.annotations.Parameter; + +import ca.uhn.fhir.tinder.AbstractGenerator.FailureException; +import ca.uhn.fhir.tinder.TinderStructuresMojo.ValueSetFileDefinition; +import ca.uhn.fhir.tinder.parser.BaseStructureParser; +import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; + +/** + * @author Bill.Denton + * + */ +public class GeneratorContext { + public enum ResourceSource {SPREADSHEET, MODEL}; + public static final ResourceSource DEFAULT_RESOURCE_SOURCE = ResourceSource.SPREADSHEET; + + private String version; + private String packageSuffix; + private String baseDir; + private List includeResources; + private List excludeResources; + private ResourceSource resourceSource = DEFAULT_RESOURCE_SOURCE; + private List valueSetFiles; + private BaseStructureParser resourceGenerator = null; + private ValueSetGenerator valueSetGenerator = null; + private DatatypeGeneratorUsingSpreadsheet datatypeGenerator = null; + + public String getBaseDir() { + return baseDir; + } + + public void setBaseDir(String baseDir) { + this.baseDir = baseDir; + } + + public DatatypeGeneratorUsingSpreadsheet getDatatypeGenerator() { + return datatypeGenerator; + } + + public void setDatatypeGenerator(DatatypeGeneratorUsingSpreadsheet datatypeGenerator) { + this.datatypeGenerator = datatypeGenerator; + } + + public List getExcludeResources() { + return excludeResources; + } + + public void setExcludeResources(List excludeResources) { + this.excludeResources = excludeResources; + } + + public List getIncludeResources() { + return includeResources; + } + public void setIncludeResources(List includeResources) { + this.includeResources = includeResources; + } + + public ResourceSource getResourceSource() { + return resourceSource; + } + + public void setResourceSource(ResourceSource resourceSource) { + this.resourceSource = resourceSource; + } + + public void setResourceSource(String resourceSource) throws FailureException { + resourceSource = StringUtils.stripToNull(resourceSource); + if (null == resourceSource) { + this.resourceSource = DEFAULT_RESOURCE_SOURCE; + } else + if (ResourceSource.SPREADSHEET.name().equalsIgnoreCase(resourceSource)) { + this.resourceSource = ResourceSource.SPREADSHEET; + } else + if (ResourceSource.MODEL.name().equalsIgnoreCase(resourceSource)) { + this.resourceSource = ResourceSource.MODEL; + } else { + throw new FailureException("Unknown resource-source option: " + resourceSource); + } + } + + public String getPackageSuffix() { + return packageSuffix; + } + + public void setPackageSuffix(String packageSuffix) { + this.packageSuffix = packageSuffix; + } + + public BaseStructureParser getResourceGenerator() { + return resourceGenerator; + } + + public void setResourceGenerator(BaseStructureParser resourceGenerator) { + this.resourceGenerator = resourceGenerator; + } + + public List getValueSetFiles() { + return valueSetFiles; + } + + public void setValueSetFiles(List valueSetFiles) { + this.valueSetFiles = valueSetFiles; + } + + public ValueSetGenerator getValueSetGenerator() { + return valueSetGenerator; + } + public void setValueSetGenerator(ValueSetGenerator valueSetGenerator) { + this.valueSetGenerator = valueSetGenerator; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public static class ProfileFileDefinition { + @Parameter(required = true) + String profileFile; + + @Parameter(required = true) + String profileSourceUrl; + + public String getProfileFile() { + return profileFile; + } + + public void setProfileFile(String profileFile) { + this.profileFile = profileFile; + } + + public String getProfileSourceUrl() { + return profileSourceUrl; + } + + public void setProfileSourceUrl(String profileSourceUrl) { + this.profileSourceUrl = profileSourceUrl; + } + } +} diff --git a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/TinderGenericMultiFileMojo.java b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/TinderGenericMultiFileMojo.java index f4088cd4a26..42cba862f57 100644 --- a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/TinderGenericMultiFileMojo.java +++ b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/TinderGenericMultiFileMojo.java @@ -1,411 +1,424 @@ -package ca.uhn.fhir.tinder; - -import ca.uhn.fhir.tinder.AbstractGenerator.ExecutionException; -import ca.uhn.fhir.tinder.AbstractGenerator.FailureException; -import ca.uhn.fhir.tinder.TinderStructuresMojo.ValueSetFileDefinition; -import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; -import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet; -import ca.uhn.fhir.tinder.parser.TargetType; -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 java.io.File; -import java.io.IOException; -import java.util.List; - -/** - * Generate files from FHIR resource/composite metadata using Velocity templates. - *

- * Generates either source or resource files for each selected resource or - * composite data type. One file is generated for each selected entity. The - * files are generated using a Velocity template that can be taken from - * inside the hapi-timder-plugin project or can be located in other projects - *

- * The following Maven plug-in configuration properties are used with this plug-in - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
AttributeDescriptionRequired
versionThe FHIR version whose resource metadata - * is to be used to generate the files
- * Valid values: dstu | dstu2 | dstu3
Yes
baseDirThe Maven project's base directory. This is used to - * possibly locate other assets within the project used in file generation.No. Defaults to: ${project.build.directory}/..
generateResourcesShould files be generated from FHIR resource metadata?
- * Valid values: true | false
One of these four options must be specified
generateDataTypesShould files be generated from FHIR composite data type metadata?
- * Valid values: true | false
generateValueSetsShould files be generated from FHIR value set metadata?
- * Valid values: true | false
generateProfilesShould files be generated from FHIR profile metadata?
- * Valid values: true | false
- *
Java source files can be generated - * for FHIR resources or composite data types. There is one file - * generated for each selected entity. The following configuration - * properties control the naming of the generated source files:
- *     <targetSourceDirectory>/<targetPackage>/<filenamePrefix>element-name<filenameSuffix>
- * where: element-name is the "title-case" name of the selected resource or composite data type.
- * Note that all dots in the targetPackage will be replaced by the path separator character when building the - * actual source file location. Also note that .java will be added to the filenameSuffix if it is not already included. - *
targetSourceDirectoryThe Maven source directory to contain the generated files.Yes when Java source files are to be generated
targetPackageThe Java package that will contain the generated classes. - * This package is generated in the <targetSourceDirectory> if needed.Yes when targetSourceDirectory is specified
filenamePrefixThe prefix string that is to be added onto the - * beginning of the resource or composite data type name to become - * the Java class name or resource file name.No
filenameSuffixSuffix that will be added onto the end of the resource - * or composite data type name to become the Java class name or resource file name.No.
- *
Maven resource files can also be generated - * for FHIR resources or composite data types. The following configuration - * properties control the naming of the generated resource files:
- *     <targetResourceDirectory>/<targetFolder>/<filenamePrefix>element-name<filenameSuffix>
- * where: element-name is the "title-case" name of the selected resource or composite data type. - *
targetResourceDirectoryThe Maven resource directory to contain the generated files.Yes when resource files are to be generated
targetFolderThe folder within the targetResourceDirectory where the generated files will be placed. - * This folder is generated in the <targetResourceDirectory> if needed.No
- *
templateThe path of one of the Velocity templates - * contained within the hapi-tinder-plugin Maven plug-in - * classpath that will be used to generate the files.One of these two options must be configured
templateFileThe full path to the Velocity template that is - * to be used to generate the files.
velocityPathWhen using the templateFile option, this property - * can be used to specify where Velocity macros and other resources are located.No. Defaults to same directory as the template file.
velocityPropertiesSpecifies the full path to a java properties file - * containing Velocity configuration propertiesNo.
includeResourcesA list of the names of the resources or composite data types that should - * be used in the file generationNo. Defaults to all defined resources except for DSTU2, - * the Binary resource is excluded and - * for DSTU3, the Conformance resource is excluded.
excludeResourcesA list of the names of the resources or composite data types that should - * excluded from the file generationNo.
valueSetFilesA list of files containing value-set resource definitions - * to be used.No. Defaults to all defined value-sets that - * are referenced from the selected resources.
profileFilesA list of files containing profile definitions - * to be used.No. Defaults to the default profile - * for each selected resource
- * - * - * - * @author Bill.Denton - * - */ -@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); - - @Parameter(required = true) - private String version; - - @Parameter(required = true, defaultValue = "${project.build.directory}/..") - private String baseDir; - - @Parameter(required = false, defaultValue="false") - private boolean generateResources; - - @Parameter(required = false, defaultValue = "false") - private boolean generateDatatypes; - - @Parameter(required = false, defaultValue = "false") - private boolean generateValueSets; - - @Parameter(required = false) - private File targetSourceDirectory; - - @Parameter(required = false) - private String targetPackage; - - @Parameter(required = false) - private String filenamePrefix; - - @Parameter(required = false) - private String filenameSuffix; - - @Parameter(required = false) - private File targetResourceDirectory; - - @Parameter(required = false) - private String targetFolder; - - // one of these two is required - @Parameter(required = false) - private String template; - @Parameter(required = false) - private File templateFile; - @Parameter(required = false) - private String velocityPath; - @Parameter(required = false) - private String velocityProperties; - - @Parameter(required = false) - private List includeResources; - - @Parameter(required = false) - private List excludeResources; - - @Parameter(required = false) - private List valueSetFiles; - - @Component - private MavenProject myProject; - - @Override - public void execute() throws MojoExecutionException, MojoFailureException { - - GeneratorContext context = new GeneratorContext(); - context.setVersion(version); - context.setBaseDir(baseDir); - context.setIncludeResources(includeResources); - context.setExcludeResources(excludeResources); - context.setValueSetFiles(valueSetFiles); - - Generator generator = new Generator(); - try { - generator.prepare(context); - } catch (ExecutionException e) { - throw new MojoExecutionException(e.getMessage(), e.getCause()); - } catch (FailureException e) { - throw new MojoFailureException(e.getMessage(), e.getCause()); - } - - /* - * Deal with the generation target - */ - TargetType targetType = null; - File targetDirectory = null; - if (targetSourceDirectory != null) { - if (targetResourceDirectory != null) { - throw new MojoFailureException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); - } - targetType = TargetType.SOURCE; - if (null == targetPackage) { - throw new MojoFailureException("The [targetPackage] property must be specified when generating Java source code."); - } - targetDirectory = new File(targetSourceDirectory, targetPackage.replace('.', File.separatorChar)); - } else - if (targetResourceDirectory != null) { - if (targetSourceDirectory != null) { - throw new MojoFailureException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); - } - targetType = TargetType.RESOURCE; - if (targetFolder != null) { - targetDirectory = new File(targetResourceDirectory, targetFolder); - } else { - targetDirectory = targetResourceDirectory; - } - if (null == targetPackage) { - targetPackage = ""; - } - } else { - throw new MojoFailureException("Either [targetSourceDirectory] or [targetResourceDirectory] must be specified."); - } - targetDirectory.mkdirs(); - ourLog.info(" * Output ["+targetType.toString()+"] Directory: " + targetDirectory.getAbsolutePath()); - - /* - * Write resources if selected - */ - ResourceGeneratorUsingSpreadsheet rp = context.getResourceGenerator(); - if (generateResources && rp != null) { - ourLog.info("Writing Resources..."); - rp.setFilenamePrefix(filenamePrefix); - rp.setFilenameSuffix(filenameSuffix); - rp.setTemplate(template); - rp.setTemplateFile(templateFile); - rp.setVelocityPath(velocityPath); - rp.setVelocityProperties(velocityProperties); - rp.writeAll(targetType, targetDirectory, null, targetPackage); - } - - /* - * Write composite datatypes - */ - DatatypeGeneratorUsingSpreadsheet dtp = context.getDatatypeGenerator(); - if (generateDatatypes && dtp != null) { - ourLog.info("Writing Composite Datatypes..."); - dtp.setFilenamePrefix(filenamePrefix); - dtp.setFilenameSuffix(filenameSuffix); - dtp.setTemplate(template); - dtp.setTemplateFile(templateFile); - dtp.setVelocityPath(velocityPath); - dtp.setVelocityProperties(velocityProperties); - dtp.writeAll(targetType, targetDirectory, null, targetPackage); - } - - /* - * Write valuesets - */ - ValueSetGenerator vsp = context.getValueSetGenerator(); - if (generateValueSets && vsp != null) { - ourLog.info("Writing ValueSet Enums..."); - vsp.setFilenamePrefix(filenamePrefix); - vsp.setFilenameSuffix(filenameSuffix); - vsp.setTemplate(template); - vsp.setTemplateFile(templateFile); - vsp.setVelocityPath(velocityPath); - vsp.setVelocityProperties(velocityProperties); - vsp.writeMarkedValueSets(targetType, targetDirectory, targetPackage); - } - - switch (targetType) { - case SOURCE: { - myProject.addCompileSourceRoot(targetSourceDirectory.getAbsolutePath()); - break; - } - case RESOURCE: { - Resource resource = new Resource(); - resource.setDirectory(targetResourceDirectory.getAbsolutePath()); - if (targetFolder != null) { - resource.addInclude(targetFolder+"/*"); - } else { - resource.addInclude("*"); - } - myProject.addResource(resource); - break; - } - default: - } - - } - - public static void main(String[] args) throws 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.targetPackage = "ca.uhn.test"; - mojo.template = "/vm/jpa_resource_provider.vm"; - mojo.targetSourceDirectory = new File("target/generated/valuesets"); - mojo.execute(); - } - - class Generator extends AbstractGenerator { - @Override - protected void logDebug(String message) { - ourLog.debug(message); - } - - @Override - protected void logInfo(String message) { - ourLog.info(message); - } - } -} +package ca.uhn.fhir.tinder; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +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 ca.uhn.fhir.tinder.AbstractGenerator.ExecutionException; +import ca.uhn.fhir.tinder.AbstractGenerator.FailureException; +import ca.uhn.fhir.tinder.TinderStructuresMojo.ValueSetFileDefinition; +import ca.uhn.fhir.tinder.parser.BaseStructureParser; +import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; +import ca.uhn.fhir.tinder.parser.TargetType; + +/** + * Generate files from FHIR resource/composite metadata using Velocity templates. + *

+ * Generates either source or resource files for each selected resource or + * composite data type. One file is generated for each selected entity. The + * files are generated using a Velocity template that can be taken from + * inside the hapi-timder-plugin project or can be located in other projects + *

+ * The following Maven plug-in configuration properties are used with this plug-in + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
AttributeDescriptionRequired
versionThe FHIR version whose resource metadata + * is to be used to generate the files
+ * Valid values: dstu2 | dstu3 | r4
Yes
baseDirThe Maven project's base directory. This is used to + * possibly locate other assets within the project used in file generation.No. Defaults to: ${project.build.directory}/..
generateResourcesShould files be generated from FHIR resource metadata?
+ * Valid values: true | false
One of these four options must be specified as true
generateDataTypesShould files be generated from FHIR composite data type metadata?
+ * Valid values: true | false
generateValueSetsShould files be generated from FHIR value set metadata?
+ * Valid values: true | false
generateProfilesShould files be generated from FHIR profile metadata?
+ * Valid values: true | false
resourceSourceWhich source of resource definitions should be processed? Valid values are:
+ *
    + *
  • spreadsheet  to cause resources to be generated based on the FHIR spreadsheets
  • + *
  • model  to cause resources to be generated based on the model structure classes
No. Defaults to: spreadsheet
+ *
Java source files can be generated + * for FHIR resources or composite data types. There is one file + * generated for each selected entity. The following configuration + * properties control the naming of the generated source files:
+ *     <targetSourceDirectory>/<targetPackage>/<filenamePrefix>element-name<filenameSuffix>
+ * where: element-name is the "title-case" name of the selected resource or composite data type.
+ * Note that all dots in the targetPackage will be replaced by the path separator character when building the + * actual source file location. Also note that .java will be added to the filenameSuffix if it is not already included. + *
targetSourceDirectoryThe Maven source directory to contain the generated files.Yes when Java source files are to be generated
targetPackageThe Java package that will contain the generated classes. + * This package is generated in the <targetSourceDirectory> if needed.Yes when targetSourceDirectory is specified
filenamePrefixThe prefix string that is to be added onto the + * beginning of the resource or composite data type name to become + * the Java class name or resource file name.No
filenameSuffixSuffix that will be added onto the end of the resource + * or composite data type name to become the Java class name or resource file name.No.
+ *
Maven resource files can also be generated + * for FHIR resources or composite data types. The following configuration + * properties control the naming of the generated resource files:
+ *     <targetResourceDirectory>/<targetFolder>/<filenamePrefix>element-name<filenameSuffix>
+ * where: element-name is the "title-case" name of the selected resource or composite data type. + *
targetResourceDirectoryThe Maven resource directory to contain the generated files.Yes when resource files are to be generated
targetFolderThe folder within the targetResourceDirectory where the generated files will be placed. + * This folder is generated in the <targetResourceDirectory> if needed.No
+ *
templateThe path of one of the Velocity templates + * contained within the hapi-tinder-plugin Maven plug-in + * classpath that will be used to generate the files.One of these two options must be configured
templateFileThe full path to the Velocity template that is + * to be used to generate the files.
velocityPathWhen using the templateFile option, this property + * can be used to specify where Velocity macros and other resources are located.No. Defaults to same directory as the template file.
velocityPropertiesSpecifies the full path to a java properties file + * containing Velocity configuration propertiesNo.
includeResourcesA list of the names of the resources or composite data types that should + * be used in the file generationNo. Defaults to all defined resources except for DSTU2, + * the Binary resource is excluded and + * for DSTU3, the Conformance resource is excluded.
excludeResourcesA list of the names of the resources or composite data types that should + * excluded from the file generationNo.
valueSetFilesA list of files containing value-set resource definitions + * to be used.No. Defaults to all defined value-sets that + * are referenced from the selected resources.
profileFilesA list of files containing profile definitions + * to be used.No. Defaults to the default profile + * for each selected resource
+ * + * + * + * @author Bill.Denton + * + */ +@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); + + @Parameter(required = true) + private String version; + + @Parameter(required = true, defaultValue = "${project.build.directory}/..") + private String baseDir; + + @Parameter(required = false, defaultValue="false") + private boolean generateResources; + + @Parameter(required = false, defaultValue = "false") + private boolean generateDatatypes; + + @Parameter(required = false, defaultValue = "false") + private boolean generateValueSets; + + @Parameter(required = false) + private File targetSourceDirectory; + + @Parameter(required = false) + private String targetPackage; + + @Parameter(required = false) + private String filenamePrefix; + + @Parameter(required = false) + private String filenameSuffix; + + @Parameter(required = false) + private File targetResourceDirectory; + + @Parameter(required = false) + private String targetFolder; + + // one of these two is required + @Parameter(required = false) + private String template; + @Parameter(required = false) + private File templateFile; + @Parameter(required = false) + private String velocityPath; + @Parameter(required = false) + private String velocityProperties; + + @Parameter(required = false) + private List includeResources; + + @Parameter(required = false) + private List excludeResources; + + @Parameter(required = false) + private String resourceSource; + + @Parameter(required = false) + private List valueSetFiles; + + @Component + private MavenProject myProject; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + GeneratorContext context = new GeneratorContext(); + Generator generator = new Generator(); + try { + context.setVersion(version); + context.setBaseDir(baseDir); + context.setIncludeResources(includeResources); + context.setExcludeResources(excludeResources); + context.setResourceSource(resourceSource); + context.setValueSetFiles(valueSetFiles); + + generator.prepare(context); + } catch (ExecutionException e) { + throw new MojoExecutionException(e.getMessage(), e.getCause()); + } catch (FailureException e) { + throw new MojoFailureException(e.getMessage(), e.getCause()); + } + + /* + * Deal with the generation target + */ + TargetType targetType = null; + File targetDirectory = null; + if (targetSourceDirectory != null) { + if (targetResourceDirectory != null) { + throw new MojoFailureException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); + } + targetType = TargetType.SOURCE; + if (null == targetPackage) { + throw new MojoFailureException("The [targetPackage] property must be specified when generating Java source code."); + } + targetDirectory = new File(targetSourceDirectory, targetPackage.replace('.', File.separatorChar)); + } else + if (targetResourceDirectory != null) { + if (targetSourceDirectory != null) { + throw new MojoFailureException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); + } + targetType = TargetType.RESOURCE; + if (targetFolder != null) { + targetDirectory = new File(targetResourceDirectory, targetFolder); + } else { + targetDirectory = targetResourceDirectory; + } + if (null == targetPackage) { + targetPackage = ""; + } + } else { + throw new MojoFailureException("Either [targetSourceDirectory] or [targetResourceDirectory] must be specified."); + } + targetDirectory.mkdirs(); + ourLog.info(" * Output ["+targetType.toString()+"] Directory: " + targetDirectory.getAbsolutePath()); + + /* + * Write resources if selected + */ + BaseStructureParser rp = context.getResourceGenerator(); + if (generateResources && rp != null) { + ourLog.info("Writing Resources..."); + rp.setFilenamePrefix(filenamePrefix); + rp.setFilenameSuffix(filenameSuffix); + rp.setTemplate(template); + rp.setTemplateFile(templateFile); + rp.setVelocityPath(velocityPath); + rp.setVelocityProperties(velocityProperties); + rp.writeAll(targetType, targetDirectory, null, targetPackage); + } + + /* + * Write composite datatypes + */ + DatatypeGeneratorUsingSpreadsheet dtp = context.getDatatypeGenerator(); + if (generateDatatypes && dtp != null) { + ourLog.info("Writing Composite Datatypes..."); + dtp.setFilenamePrefix(filenamePrefix); + dtp.setFilenameSuffix(filenameSuffix); + dtp.setTemplate(template); + dtp.setTemplateFile(templateFile); + dtp.setVelocityPath(velocityPath); + dtp.setVelocityProperties(velocityProperties); + dtp.writeAll(targetType, targetDirectory, null, targetPackage); + } + + /* + * Write valuesets + */ + ValueSetGenerator vsp = context.getValueSetGenerator(); + if (generateValueSets && vsp != null) { + ourLog.info("Writing ValueSet Enums..."); + vsp.setFilenamePrefix(filenamePrefix); + vsp.setFilenameSuffix(filenameSuffix); + vsp.setTemplate(template); + vsp.setTemplateFile(templateFile); + vsp.setVelocityPath(velocityPath); + vsp.setVelocityProperties(velocityProperties); + vsp.writeMarkedValueSets(targetType, targetDirectory, targetPackage); + } + + switch (targetType) { + case SOURCE: { + myProject.addCompileSourceRoot(targetSourceDirectory.getAbsolutePath()); + break; + } + case RESOURCE: { + Resource resource = new Resource(); + resource.setDirectory(targetResourceDirectory.getAbsolutePath()); + if (targetFolder != null) { + resource.addInclude(targetFolder+"/*"); + } else { + resource.addInclude("*"); + } + myProject.addResource(resource); + break; + } + default: + } + + } + + public static void main(String[] args) throws 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.targetPackage = "ca.uhn.test"; + mojo.template = "/vm/jpa_resource_provider.vm"; + mojo.targetSourceDirectory = new File("target/generated/valuesets"); + mojo.execute(); + } + + class Generator extends AbstractGenerator { + @Override + protected void logDebug(String message) { + ourLog.debug(message); + } + + @Override + protected void logInfo(String message) { + ourLog.info(message); + } + } +} diff --git a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/TinderGenericSingleFileMojo.java b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/TinderGenericSingleFileMojo.java index 5b2137f22d3..1f4339280c4 100644 --- a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/TinderGenericSingleFileMojo.java +++ b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/TinderGenericSingleFileMojo.java @@ -1,432 +1,451 @@ -package ca.uhn.fhir.tinder; - -import ca.uhn.fhir.tinder.AbstractGenerator.ExecutionException; -import ca.uhn.fhir.tinder.AbstractGenerator.FailureException; -import ca.uhn.fhir.tinder.TinderStructuresMojo.ValueSetFileDefinition; -import ca.uhn.fhir.tinder.parser.BaseStructureSpreadsheetParser; -import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; -import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet; -import ca.uhn.fhir.tinder.parser.TargetType; -import org.apache.commons.lang.WordUtils; -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 java.io.*; -import java.util.List; - -/** - * Generate a single file based on resource or composite type metadata. - *

- * Generates either a source or resource file containing all selected resources or - * composite data types. The file is - * generated using a Velocity template that can be taken from - * inside the hapi-timder-plugin project or can be located in other projects - *

- * The following Maven plug-in configuration properties are used with this plug-in - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
AttributeDescriptionRequired
versionThe FHIR version whose resource metadata - * is to be used to generate the files
- * Valid values: dstu | dstu2 | dstu3
Yes
baseDirThe Maven project's base directory. This is used to - * possibly locate other assets within the project used in file generation.No. Defaults to: ${project.build.directory}/..
generateResourcesShould files be generated from FHIR resource metadata?
- * Valid values: true | false
One of these two options must be specified
generateDataTypesShould files be generated from FHIR composite data type metadata?
- * Valid values: true | false
- *
Java source files can be generated - * for FHIR resources or composite data types. There is one file - * generated for each selected entity. The following configuration - * properties control the naming of the generated source files:
- *     <targetSourceDirectory>/<targetPackage>/<targetFile>
- * Note that all dots in the targetPackage will be replaced by the path separator character when building the - * actual source file location. Also note that .java will be added to the targetFile if it is not already included. - *
targetSourceDirectoryThe Maven source directory to contain the generated file.Yes when a Java source file is to be generated
targetPackageThe Java package that will contain the generated classes. - * This package is generated in the <targetSourceDirectory> if needed.Yes when targetSourceDirectory is specified
packageBaseThe base Java package for related classes. This property - * can be used to reference class in other places in a folder structure.No
targetFileThe name of the file to be generatedYes
- *
Maven resource files can also be generated - * for FHIR resources or composite data types. The following configuration - * properties control the naming of the generated resource files:
- *     <targetResourceDirectory>/<targetFolder>/<targetFile>
- *
targetResourceDirectoryThe Maven resource directory to contain the generated file.Yes when a resource file is to be generated
targetFolderThe folder within the targetResourceDirectory where the generated file will be placed. - * This folder is generated in the <targetResourceDirectory> if needed.No
- *
templateThe path of one of the Velocity templates - * contained within the hapi-tinder-plugin Maven plug-in - * classpath that will be used to generate the files.One of these two options must be configured
templateFileThe full path to the Velocity template that is - * to be used to generate the files.
velocityPathWhen using the templateFile option, this property - * can be used to specify where Velocity macros and other resources are located.No. Defaults to same directory as the template file.
velocityPropertiesSpecifies the full path to a java properties file - * containing Velocity configuration propertiesNo.
includeResourcesA list of the names of the resources or composite data types that should - * be used in the file generationNo. Defaults to all defined resources except for DSTU2, - * the Binary resource is excluded and - * for DSTU3, the Conformance resource is excluded.
excludeResourcesA list of the names of the resources or composite data types that should - * excluded from the file generationNo.
valueSetFilesA list of files containing value-set resource definitions - * to be used.No. Defaults to all defined value-sets that - * are referenced from the selected resources.
profileFilesA list of files containing profile definitions - * to be used.No. Defaults to the default profile - * for each selected resource
- * - * - * - * @author Bill.Denton - * - */ -@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); - - @Parameter(required = true) - private String version; - - @Parameter(required = true, defaultValue = "${project.build.directory}/..") - private String baseDir; - - @Parameter(required = false, defaultValue="false") - private boolean generateResources; - - @Parameter(required = false, defaultValue = "false") - private boolean generateDatatypes; - - @Parameter(required = false) - private File targetSourceDirectory; - - @Parameter(required = false) - private String targetPackage; - - @Parameter(required = false) - private String packageBase; - - @Parameter(required = false) - private File targetResourceDirectory; - - @Parameter(required = false) - private String targetFolder; - - @Parameter(required = false) - private String targetFile; - - // one of these two is required - @Parameter(required = false) - private String template; - @Parameter(required = false) - private File templateFile; - @Parameter(required = false) - private String velocityPath; - @Parameter(required = false) - private String velocityProperties; - - @Parameter(required = false) - private List includeResources; - - @Parameter(required = false) - private List excludeResources; - - @Parameter(required = false) - private List valueSetFiles; - - @Component - private MavenProject myProject; - - @Override - public void execute() throws MojoExecutionException, MojoFailureException { - - GeneratorContext context = new GeneratorContext(); - context.setVersion(version); - context.setBaseDir(baseDir); - context.setIncludeResources(includeResources); - context.setExcludeResources(excludeResources); - context.setValueSetFiles(valueSetFiles); - - Generator generator = new Generator(); - try { - generator.prepare(context); - } catch (ExecutionException e) { - throw new MojoExecutionException(e.getMessage(), e.getCause()); - } catch (FailureException e) { - throw new MojoFailureException(e.getMessage(), e.getCause()); - } - - try { - /* - * Deal with the generation target - */ - TargetType targetType = null; - File targetDirectory = null; - if (null == targetFile) { - throw new MojoFailureException("The [targetFile] parameter is required."); - } - if (targetSourceDirectory != null) { - if (targetResourceDirectory != null) { - throw new MojoFailureException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); - } - targetType = TargetType.SOURCE; - if (null == targetPackage) { - throw new MojoFailureException("The [targetPackage] property must be specified when generating Java source code."); - } - targetDirectory = new File(targetSourceDirectory, targetPackage.replace('.', File.separatorChar)); - if (!targetFile.endsWith(".java")) { - targetFile += ".java"; - } - } else - if (targetResourceDirectory != null) { - if (targetSourceDirectory != null) { - throw new MojoFailureException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); - } - targetType = TargetType.RESOURCE; - if (targetFolder != null) { - targetFolder = targetFolder.replace('\\', '/'); - targetFolder = targetFolder.replace('/', File.separatorChar); - targetDirectory = new File(targetResourceDirectory, targetFolder); - } else { - targetDirectory = targetResourceDirectory; - } - if (null == targetPackage) { - targetPackage = ""; - } - } else { - throw new MojoFailureException("Either [targetSourceDirectory] or [targetResourceDirectory] must be specified."); - } - ourLog.info(" * Output ["+targetType.toString()+"] file ["+targetFile+"] in directory: " + targetDirectory.getAbsolutePath()); - targetDirectory.mkdirs(); - File target = new File(targetDirectory, targetFile); - OutputStreamWriter targetWriter = new OutputStreamWriter(new FileOutputStream(target, false), "UTF-8"); - - /* - * Next, deal with the template and initialize velocity - */ - VelocityEngine v = VelocityHelper.configureVelocityEngine(templateFile, velocityPath, velocityProperties); - InputStream templateIs = null; - if (templateFile != null) { - templateIs = new FileInputStream(templateFile); - } else { - templateIs = this.getClass().getResourceAsStream(template); - } - InputStreamReader templateReader = new InputStreamReader(templateIs); - - /* - * build new Velocity Context - */ - VelocityContext ctx = new VelocityContext(); - if (packageBase != null) { - ctx.put("packageBase", packageBase); - } else - if (targetPackage != null) { - int ix = targetPackage.lastIndexOf('.'); - if (ix > 0) { - ctx.put("packageBase", targetPackage.subSequence(0, ix)); - } else { - ctx.put("packageBase", targetPackage); - } - } - ctx.put("targetPackage", targetPackage); - ctx.put("targetFolder", targetFolder); - ctx.put("version", version); - ctx.put("isRi", BaseStructureSpreadsheetParser.determineVersionEnum(version).isRi()); - ctx.put("hash", "#"); - 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); - - /* - * Write resources if selected - */ - ResourceGeneratorUsingSpreadsheet rp = context.getResourceGenerator(); - if (generateResources && rp != null) { - ourLog.info("Writing Resources..."); - ctx.put("resources", rp.getResources()); - v.evaluate(ctx, targetWriter, "", templateReader); - targetWriter.close(); - } else { - DatatypeGeneratorUsingSpreadsheet dtp = context.getDatatypeGenerator(); - if (generateDatatypes && dtp != null) { - ourLog.info("Writing DataTypes..."); - ctx.put("datatypes", dtp.getResources()); - v.evaluate(ctx, targetWriter, "", templateReader); - targetWriter.close(); - } - } - - switch (targetType) { - case SOURCE: { - myProject.addCompileSourceRoot(targetSourceDirectory.getAbsolutePath()); - break; - } - case RESOURCE: { - Resource resource = new Resource(); - resource.setDirectory(targetResourceDirectory.getAbsolutePath()); - String resName = targetFile; - if (targetFolder != null) { - resName = targetFolder+File.separator+targetFile; - } - resource.addInclude(resName); - myProject.addResource(resource); - break; - } - default: - } - - } catch (Exception e) { - throw new MojoFailureException("Failed to generate file", e); - } - } - - public static void main(String[] args) throws 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.targetPackage = "ca.uhn.test"; - mojo.targetSourceDirectory = new File("target/generated/valuesets"); - mojo.targetFile = "tmp_beans.xml"; - mojo.execute(); - } - - class Generator extends AbstractGenerator { - @Override - protected void logDebug(String message) { - ourLog.debug(message); - } - - @Override - protected void logInfo(String message) { - ourLog.info(message); - } - } -} +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.List; + +import org.apache.commons.lang.WordUtils; +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.tinder.AbstractGenerator.ExecutionException; +import ca.uhn.fhir.tinder.AbstractGenerator.FailureException; +import ca.uhn.fhir.tinder.TinderStructuresMojo.ValueSetFileDefinition; +import ca.uhn.fhir.tinder.parser.BaseStructureParser; +import ca.uhn.fhir.tinder.parser.BaseStructureSpreadsheetParser; +import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; +import ca.uhn.fhir.tinder.parser.TargetType; + +/** + * Generate a single file based on resource or composite type metadata. + *

+ * Generates either a source or resource file containing all selected resources or + * composite data types. The file is + * generated using a Velocity template that can be taken from + * inside the hapi-timder-plugin project or can be located in other projects + *

+ * The following Maven plug-in configuration properties are used with this plug-in + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
AttributeDescriptionRequired
versionThe FHIR version whose resource metadata + * is to be used to generate the files
+ * Valid values: dstu2 | dstu3 | r4
Yes
baseDirThe Maven project's base directory. This is used to + * possibly locate other assets within the project used in file generation.No. Defaults to: ${project.build.directory}/..
generateResourcesShould files be generated from FHIR resource metadata?
+ * Valid values: true | false
One of these two options must be specified as true
generateDataTypesShould files be generated from FHIR composite data type metadata?
+ * Valid values: true | false
resourceSourceWhich source of resource definitions should be processed? Valid values are:
+ *
    + *
  • spreadsheet  to cause resources to be generated based on the FHIR spreadsheets
  • + *
  • model  to cause resources to be generated based on the model structure classes
No. Defaults to: spreadsheet
+ *
Java source files can be generated + * for FHIR resources or composite data types. There is one file + * generated for each selected entity. The following configuration + * properties control the naming of the generated source files:
+ *     <targetSourceDirectory>/<targetPackage>/<targetFile>
+ * Note that all dots in the targetPackage will be replaced by the path separator character when building the + * actual source file location. Also note that .java will be added to the targetFile if it is not already included. + *
targetSourceDirectoryThe Maven source directory to contain the generated file.Yes when a Java source file is to be generated
targetPackageThe Java package that will contain the generated classes. + * This package is generated in the <targetSourceDirectory> if needed.Yes when targetSourceDirectory is specified
packageBaseThe base Java package for related classes. This property + * can be used to reference class in other places in a folder structure.No
targetFileThe name of the file to be generatedYes
+ *
Maven resource files can also be generated + * for FHIR resources or composite data types. The following configuration + * properties control the naming of the generated resource files:
+ *     <targetResourceDirectory>/<targetFolder>/<targetFile>
+ *
targetResourceDirectoryThe Maven resource directory to contain the generated file.Yes when a resource file is to be generated
targetFolderThe folder within the targetResourceDirectory where the generated file will be placed. + * This folder is generated in the <targetResourceDirectory> if needed.No
+ *
templateThe path of one of the Velocity templates + * contained within the hapi-tinder-plugin Maven plug-in + * classpath that will be used to generate the files.One of these two options must be configured
templateFileThe full path to the Velocity template that is + * to be used to generate the files.
velocityPathWhen using the templateFile option, this property + * can be used to specify where Velocity macros and other resources are located.No. Defaults to same directory as the template file.
velocityPropertiesSpecifies the full path to a java properties file + * containing Velocity configuration propertiesNo.
includeResourcesA list of the names of the resources or composite data types that should + * be used in the file generationNo. Defaults to all defined resources except for DSTU2, + * the Binary resource is excluded and + * for DSTU3, the Conformance resource is excluded.
excludeResourcesA list of the names of the resources or composite data types that should + * excluded from the file generationNo.
valueSetFilesA list of files containing value-set resource definitions + * to be used.No. Defaults to all defined value-sets that + * are referenced from the selected resources.
profileFilesA list of files containing profile definitions + * to be used.No. Defaults to the default profile + * for each selected resource
+ * + * + * + * @author Bill.Denton + * + */ +@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); + + @Parameter(required = true) + private String version; + + @Parameter(required = true, defaultValue = "${project.build.directory}/..") + private String baseDir; + + @Parameter(required = false, defaultValue="false") + private boolean generateResources; + + @Parameter(required = false, defaultValue = "false") + private boolean generateDatatypes; + + @Parameter(required = false) + private File targetSourceDirectory; + + @Parameter(required = false) + private String targetPackage; + + @Parameter(required = false) + private String packageBase; + + @Parameter(required = false) + private File targetResourceDirectory; + + @Parameter(required = false) + private String targetFolder; + + @Parameter(required = false) + private String targetFile; + + // one of these two is required + @Parameter(required = false) + private String template; + @Parameter(required = false) + private File templateFile; + @Parameter(required = false) + private String velocityPath; + @Parameter(required = false) + private String velocityProperties; + + @Parameter(required = false) + private List includeResources; + + @Parameter(required = false) + private List excludeResources; + + @Parameter(required = false) + private String resourceSource; + + @Parameter(required = false) + private List valueSetFiles; + + @Component + private MavenProject myProject; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + GeneratorContext context = new GeneratorContext(); + Generator generator = new Generator(); + try { + context.setVersion(version); + context.setBaseDir(baseDir); + context.setIncludeResources(includeResources); + context.setExcludeResources(excludeResources); + context.setResourceSource(resourceSource); + context.setValueSetFiles(valueSetFiles); + + generator.prepare(context); + } catch (ExecutionException e) { + throw new MojoExecutionException(e.getMessage(), e.getCause()); + } catch (FailureException e) { + throw new MojoFailureException(e.getMessage(), e.getCause()); + } + + try { + /* + * Deal with the generation target + */ + TargetType targetType = null; + File targetDirectory = null; + if (null == targetFile) { + throw new MojoFailureException("The [targetFile] parameter is required."); + } + if (targetSourceDirectory != null) { + if (targetResourceDirectory != null) { + throw new MojoFailureException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); + } + targetType = TargetType.SOURCE; + if (null == targetPackage) { + throw new MojoFailureException("The [targetPackage] property must be specified when generating Java source code."); + } + targetDirectory = new File(targetSourceDirectory, targetPackage.replace('.', File.separatorChar)); + if (!targetFile.endsWith(".java")) { + targetFile += ".java"; + } + } else + if (targetResourceDirectory != null) { + if (targetSourceDirectory != null) { + throw new MojoFailureException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); + } + targetType = TargetType.RESOURCE; + if (targetFolder != null) { + targetFolder = targetFolder.replace('\\', '/'); + targetFolder = targetFolder.replace('/', File.separatorChar); + targetDirectory = new File(targetResourceDirectory, targetFolder); + } else { + targetDirectory = targetResourceDirectory; + } + if (null == targetPackage) { + targetPackage = ""; + } + } else { + throw new MojoFailureException("Either [targetSourceDirectory] or [targetResourceDirectory] must be specified."); + } + ourLog.info(" * Output ["+targetType.toString()+"] file ["+targetFile+"] in directory: " + targetDirectory.getAbsolutePath()); + targetDirectory.mkdirs(); + File target = new File(targetDirectory, targetFile); + OutputStreamWriter targetWriter = new OutputStreamWriter(new FileOutputStream(target, false), "UTF-8"); + + /* + * Next, deal with the template and initialize velocity + */ + VelocityEngine v = VelocityHelper.configureVelocityEngine(templateFile, velocityPath, velocityProperties); + InputStream templateIs = null; + if (templateFile != null) { + templateIs = new FileInputStream(templateFile); + } else { + templateIs = this.getClass().getResourceAsStream(template); + } + InputStreamReader templateReader = new InputStreamReader(templateIs); + + /* + * build new Velocity Context + */ + VelocityContext ctx = new VelocityContext(); + if (packageBase != null) { + ctx.put("packageBase", packageBase); + } else + if (targetPackage != null) { + int ix = targetPackage.lastIndexOf('.'); + if (ix > 0) { + ctx.put("packageBase", targetPackage.subSequence(0, ix)); + } else { + ctx.put("packageBase", targetPackage); + } + } + ctx.put("targetPackage", targetPackage); + ctx.put("targetFolder", targetFolder); + ctx.put("version", version); + ctx.put("isRi", BaseStructureSpreadsheetParser.determineVersionEnum(version).isRi()); + ctx.put("hash", "#"); + 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); + + /* + * Write resources if selected + */ + BaseStructureParser rp = context.getResourceGenerator(); + if (generateResources && rp != null) { + ourLog.info("Writing Resources..."); + ctx.put("resources", rp.getResources()); + v.evaluate(ctx, targetWriter, "", templateReader); + targetWriter.close(); + } else { + DatatypeGeneratorUsingSpreadsheet dtp = context.getDatatypeGenerator(); + if (generateDatatypes && dtp != null) { + ourLog.info("Writing DataTypes..."); + ctx.put("datatypes", dtp.getResources()); + v.evaluate(ctx, targetWriter, "", templateReader); + targetWriter.close(); + } + } + + switch (targetType) { + case SOURCE: { + myProject.addCompileSourceRoot(targetSourceDirectory.getAbsolutePath()); + break; + } + case RESOURCE: { + Resource resource = new Resource(); + resource.setDirectory(targetResourceDirectory.getAbsolutePath()); + String resName = targetFile; + if (targetFolder != null) { + resName = targetFolder+File.separator+targetFile; + } + resource.addInclude(resName); + myProject.addResource(resource); + break; + } + default: + } + + } catch (Exception e) { + throw new MojoFailureException("Failed to generate file", e); + } + } + + public static void main(String[] args) throws 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.targetPackage = "ca.uhn.test"; + mojo.targetSourceDirectory = new File("target/generated/valuesets"); + mojo.targetFile = "tmp_beans.xml"; + mojo.execute(); + } + + class Generator extends AbstractGenerator { + @Override + protected void logDebug(String message) { + ourLog.debug(message); + } + + @Override + protected void logInfo(String message) { + ourLog.info(message); + } + } +} diff --git a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ant/TinderGeneratorTask.java b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ant/TinderGeneratorTask.java index 057b279f289..e45f0a190f4 100644 --- a/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ant/TinderGeneratorTask.java +++ b/hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/ant/TinderGeneratorTask.java @@ -1,650 +1,675 @@ -package ca.uhn.fhir.tinder.ant; -/* - * #%L - * HAPI Tinder Plugin - * %% - * Copyright (C) 2014 - 2016 University Health Network - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.tinder.AbstractGenerator; -import ca.uhn.fhir.tinder.AbstractGenerator.ExecutionException; -import ca.uhn.fhir.tinder.AbstractGenerator.FailureException; -import ca.uhn.fhir.tinder.GeneratorContext; -import ca.uhn.fhir.tinder.TinderStructuresMojo.ValueSetFileDefinition; -import ca.uhn.fhir.tinder.ValueSetGenerator; -import ca.uhn.fhir.tinder.VelocityHelper; -import ca.uhn.fhir.tinder.parser.BaseStructureSpreadsheetParser; -import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; -import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet; -import ca.uhn.fhir.tinder.parser.TargetType; -import org.apache.commons.lang.WordUtils; -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Task; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.VelocityEngine; -import org.apache.velocity.tools.generic.EscapeTool; - -import java.io.*; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -/** -/** - * Generate files from FHIR resource/composite metadata using Velocity templates. - *

- * Generates either source or resource files for each selected resource or - * composite data type. One file is generated for each selected entity. The - * files are generated using a Velocity template that can be taken from - * inside the hapi-timder-plugin project or can be located in other projects - *

- * The following Ant task properties are used - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
AttributeDescriptionRequired
versionThe FHIR version whose resource metadata - * is to be used to generate the files
- * Valid values: dstu | dstu2 | dstu3
Yes
projectHomeThe project's base directory. This is used to - * possibly locate other assets within the project used in file generation.No. Defaults to: ${basedir}/..
generateResourcesShould files be generated from FHIR resource metadata?
- * Valid values: true | false
At least one of these four options must be specified
generateDataTypesShould files be generated from FHIR composite data type metadata?
- * Valid values: true | false
generateValueSetsShould files be generated from FHIR value set metadata?
- * This option can only be used if generating multiple files (one file per value-set.)
- * Valid values: true | false
generateProfilesShould files be generated from FHIR profile metadata?
- * This option can only be used if generating multiple files (one file per profile.)
- * Valid values: true | false
- *
Java source files can be generated - * for FHIR resources or composite data types. Source files can be - * generated for each selected entity or a single source file can - * be generated containing all of the selected entity. The following configuration - * properties control the naming of the generated source files: - *

The following properties will be used when generating multiple source files:
- *     <targetSourceDirectory>/<targetPackage>/<filenamePrefix>element-name<filenameSuffix>
- *     where: element-name is the "title-case" name of the selected resource or composite data type. - *

The following properties will be used when generating a single source file:
- *     <targetSourceDirectory>/<targetPackage>/<targetFile> - *

- * Note that all dots in the targetPackage will be replaced by the path separator character when building the - * actual source file location. Also note that .java will be added to the filenameSuffix or targetFile if it is not already included. - *

targetSourceDirectoryThe source directory to contain the generated Java packages and classes.Yes when Java source files are to be generated
targetPackageThe Java package that will contain the generated classes. - * This package is generated in the <targetSourceDirectory> if needed.Yes when targetSourceDirectory is specified
packageBaseThe base Java package for related classes. This property - * can be used to reference class in other places in a folder structure.No
targetFileThe name of the file to be generatedYes when generating a single file containing all selected elements
filenamePrefixThe prefix string that is to be added onto the - * beginning of the resource or composite data type name to become - * the Java class name or resource file name.No
filenameSuffixSuffix that will be added onto the end of the resource - * or composite data type name to become the Java class name or resource file name.No.
- *
Resource (non-Java) files can also be generated - * for FHIR resources or composite data types. a file can be - * generated for each selected entity or a single file can - * be generated containing all of the selected entity. The following configuration - * properties control the naming of the generated files: - *

The following properties will be used when generating multiple files (one for each selected element):
- *     <targetResourceDirectory>/<targetFolder>/<filenamePrefix>element-name<filenameSuffix>
- *     where: element-name is the "title-case" name of the selected resource or composite data type. - *

The following properties will be used when generating a single file containing all selected elements:
- *     <targetResourceDirectory>/<targetFolder>/<targetFile> - *

targetResourceDirectoryThe resource directory to contain the generated files.Yes when resource files are to be generated
targetFolderThe folder within the targetResourceDirectory where the generated files will be placed. - * This folder is generated in the <targetResourceDirectory> if needed.No
- *
templateThe path of one of the Velocity templates - * contained within the hapi-tinder-plugin Maven plug-in - * classpath that will be used to generate the files.One of these two options must be configured
templateFileThe full path to the Velocity template that is - * to be used to generate the files.
velocityPathWhen using the templateFile option, this property - * can be used to specify where Velocity macros and other resources are located.No. Defaults to same directory as the template file.
velocityPropertiesSpecifies the full path to a java properties file - * containing Velocity configuration propertiesNo.
includeResourcesA list of the names of the resources or composite data types that should - * be used in the file generationNo. Defaults to all defined resources except for DSTU2, - * the Binary resource is excluded and - * for DSTU3, the Conformance resource is excluded.
excludeResourcesA list of the names of the resources or composite data types that should - * excluded from the file generationNo.
valueSetFilesA list of files containing value-set resource definitions - * to be used.No. Defaults to all defined value-sets that - * are referenced from the selected resources.
profileFilesA list of files containing profile definitions - * to be used.No. Defaults to the default profile - * for each selected resource
- * - * - * - * @author Bill Denton - * - */ -public class TinderGeneratorTask extends Task { - - private String version; - - private String projectHome; - - private boolean generateResources; - - private boolean generateDatatypes; - - private boolean generateValueSets; - - private boolean generateProfiles; - - private File targetSourceDirectory; - - private String targetPackage; - - private String packageBase; - - private String targetFile; - - private String filenamePrefix; - - private String filenameSuffix; - - private File targetResourceDirectory; - - private String targetFolder; - - // one of these two is required - private String template; - private File templateFile; - - private String velocityPath; - - private String velocityProperties; - - private List includeResources; - - private List excludeResources; - - private List valueSetFiles; - - private boolean verbose; - - private FhirContext fhirContext; // set from version in validateAttributes - - /** - * - */ - public TinderGeneratorTask () { - super(); - } - - protected void cleanup () { - } - - @Override - public void execute () throws BuildException { - validateAttributes(); - - - GeneratorContext context = new GeneratorContext(); - context.setVersion(version); - context.setBaseDir(projectHome); - context.setIncludeResources(includeResources); - context.setExcludeResources(excludeResources); - context.setValueSetFiles(valueSetFiles); - - Generator generator = new Generator(); - try { - generator.prepare(context); - } catch (ExecutionException e) { - throw new BuildException(e.getMessage(), e.getCause()); - } catch (FailureException e) { - throw new BuildException(e.getMessage(), e.getCause()); - } - - /* - * Deal with the generation target - */ - TargetType targetType = null; - File targetDirectory = null; - if (targetSourceDirectory != null) { - if (targetResourceDirectory != null) { - throw new BuildException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); - } - targetType = TargetType.SOURCE; - if (null == targetPackage) { - throw new BuildException("The [targetPackage] property must be specified when generating Java source code."); - } - targetDirectory = new File(targetSourceDirectory, targetPackage.replace('.', File.separatorChar)); - } else - if (targetResourceDirectory != null) { - if (targetSourceDirectory != null) { - throw new BuildException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); - } - targetType = TargetType.RESOURCE; - if (targetFolder != null) { - targetDirectory = new File(targetResourceDirectory, targetFolder); - } else { - targetDirectory = targetResourceDirectory; - } - if (null == targetPackage) { - targetPackage = ""; - } - } else { - throw new BuildException("Either [targetSourceDirectory] or [targetResourceDirectory] must be specified."); - } - targetDirectory.mkdirs(); - log(" * Output ["+targetType.toString()+"] Directory: " + targetDirectory.getAbsolutePath()); - - try { - /* - * Single file with all elements - */ - if (targetFile != null) { - if (targetType == TargetType.SOURCE) { - if (!targetFile.endsWith(".java")) { - targetFile += ".java"; - } - } - File target = new File(targetDirectory, targetFile); - OutputStreamWriter targetWriter = new OutputStreamWriter(new FileOutputStream(target, false), "UTF-8"); - - /* - * Next, deal with the template and initialize velocity - */ - VelocityEngine v = VelocityHelper.configureVelocityEngine(templateFile, velocityPath, velocityProperties); - InputStream templateIs = null; - if (templateFile != null) { - templateIs = new FileInputStream(templateFile); - } else { - templateIs = this.getClass().getResourceAsStream(template); - } - InputStreamReader templateReader = new InputStreamReader(templateIs); - - /* - * build new Velocity Context - */ - VelocityContext ctx = new VelocityContext(); - if (packageBase != null) { - ctx.put("packageBase", packageBase); - } else - if (targetPackage != null) { - int ix = targetPackage.lastIndexOf('.'); - if (ix > 0) { - ctx.put("packageBase", targetPackage.subSequence(0, ix)); - } else { - ctx.put("packageBase", targetPackage); - } - } - ctx.put("targetPackage", targetPackage); - ctx.put("targetFolder", targetFolder); - ctx.put("version", version); - ctx.put("isRi", BaseStructureSpreadsheetParser.determineVersionEnum(version).isRi()); - ctx.put("hash", "#"); - 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); - - /* - * Write resources if selected - */ - ResourceGeneratorUsingSpreadsheet rp = context.getResourceGenerator(); - if (generateResources && rp != null) { - log("Writing Resources..."); - ctx.put("resources", rp.getResources()); - v.evaluate(ctx, targetWriter, "", templateReader); - targetWriter.close(); - } else { - DatatypeGeneratorUsingSpreadsheet dtp = context.getDatatypeGenerator(); - if (generateDatatypes && dtp != null) { - log("Writing DataTypes..."); - ctx.put("datatypes", dtp.getResources()); - v.evaluate(ctx, targetWriter, "", templateReader); - targetWriter.close(); - } - } - - /* - * Multiple files.. one for each element - */ - } else { - /* - * Write resources if selected - */ - ResourceGeneratorUsingSpreadsheet rp = context.getResourceGenerator(); - if (generateResources && rp != null) { - log("Writing Resources..."); - rp.setFilenamePrefix(filenamePrefix); - rp.setFilenameSuffix(filenameSuffix); - rp.setTemplate(template); - rp.setTemplateFile(templateFile); - rp.setVelocityPath(velocityPath); - rp.setVelocityProperties(velocityProperties); - rp.writeAll(targetType, targetDirectory, null, targetPackage); - } - - /* - * Write composite datatypes - */ - DatatypeGeneratorUsingSpreadsheet dtp = context.getDatatypeGenerator(); - if (generateDatatypes && dtp != null) { - log("Writing Composite Datatypes..."); - dtp.setFilenamePrefix(filenamePrefix); - dtp.setFilenameSuffix(filenameSuffix); - dtp.setTemplate(template); - dtp.setTemplateFile(templateFile); - dtp.setVelocityPath(velocityPath); - dtp.setVelocityProperties(velocityProperties); - dtp.writeAll(targetType, targetDirectory, null, targetPackage); - } - - /* - * Write valuesets - */ - ValueSetGenerator vsp = context.getValueSetGenerator(); - if (generateValueSets && vsp != null) { - log("Writing ValueSet Enums..."); - vsp.setFilenamePrefix(filenamePrefix); - vsp.setFilenameSuffix(filenameSuffix); - vsp.setTemplate(template); - vsp.setTemplateFile(templateFile); - vsp.setVelocityPath(velocityPath); - vsp.setVelocityProperties(velocityProperties); - vsp.writeMarkedValueSets(targetType, targetDirectory, targetPackage); - } - - } - - } catch (Exception e) { - if (e instanceof BuildException) { - throw (BuildException)e; - } - log("Caught exception: "+e.getClass().getName()+" ["+e.getMessage()+"]", 1); - e.printStackTrace(); - throw new BuildException("Error processing "+getTaskName()+" task.", e); - } finally { - cleanup(); - } - } - - public void setExcludeResources(String names) { - if (null == this.excludeResources) { - this.excludeResources = new ArrayList(); - } - if (names != null) { - StringTokenizer tokens = new StringTokenizer(names, ", \t\r\n"); - while (tokens.hasMoreTokens()) { - String token = tokens.nextToken(); - this.excludeResources.add(token.trim()); - } - } - } - - public void setFilenamePrefix(String filenamePrefix) { - this.filenamePrefix = filenamePrefix; - } - - public void setFilenameSuffix(String filenameSuffix) { - this.filenameSuffix = filenameSuffix; - } - - public void setGenerateDatatypes(boolean generateDatatypes) { - this.generateDatatypes = generateDatatypes; - } - - public void setGenerateProfiles(boolean generateProfiles) { - this.generateProfiles = generateProfiles; - } - - public void setGenerateResources(boolean generateResources) { - this.generateResources = generateResources; - } - - public void setGenerateValueSets(boolean generateValueSets) { - this.generateValueSets = generateValueSets; - } - - public void setIncludeResources(String names) { - if (null == this.includeResources) { - this.includeResources = new ArrayList(); - } - if (names != null) { - StringTokenizer tokens = new StringTokenizer(names, ", \t\r\n"); - while (tokens.hasMoreTokens()) { - String token = tokens.nextToken(); - this.includeResources.add(token.trim()); - } - } - } - - public void setPackageBase(String packageBase) { - this.packageBase = packageBase; - } - - public void setProjectHome(String projectHome) { - this.projectHome = projectHome; - } - - public void setTargetFile(String targetFile) { - this.targetFile = targetFile; - } - - public void setTargetFolder(String targetFolder) { - this.targetFolder = targetFolder; - } - - public void setTargetPackage(String targetPackage) { - this.targetPackage = targetPackage; - } - - public void setTargetResourceDirectory(File targetResourceDirectory) { - this.targetResourceDirectory = targetResourceDirectory; - } - - public void setTargetSourceDirectory(File targetSourceDirectory) { - this.targetSourceDirectory = targetSourceDirectory; - } - - public void setTemplate(String template) { - this.template = template; - } - - public void setTemplateFile(File templateFile) { - this.templateFile = templateFile; - } - - public void setValueSetFiles(String names) { - if (null == this.valueSetFiles) { - this.valueSetFiles = new ArrayList(); - } - if (names != null) { - StringTokenizer tokens = new StringTokenizer(names, ", \t\r\n"); - while (tokens.hasMoreTokens()) { - String token = tokens.nextToken(); - ValueSetFileDefinition def = new ValueSetFileDefinition(); - def.setValueSetFile(token.trim()); - this.valueSetFiles.add(def); - } - } - } - - public void setVelocityPath(String velocityPath) { - this.velocityPath = velocityPath; - } - - public void setVelocityProperties(String velocityProperties) { - this.velocityProperties = velocityProperties; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - public void setVersion(String version) { - this.version = version; - } - - protected void validateAttributes () throws BuildException { - if (null == version) { - throw new BuildException("The "+this.getTaskName()+" task requires \"version\" attribute."); - } - if (null == template) { - if (null == templateFile) { - throw new BuildException("The "+this.getTaskName()+" task requires \"template\" or \"templateFile\" attribute."); - } - if (!templateFile.exists()) { - throw new BuildException("The Velocity template file ["+templateFile.getAbsolutePath()+"] does not exist."); - } - if (!templateFile.canRead()) { - throw new BuildException("The Velocity template file ["+templateFile.getAbsolutePath()+"] cannot be read."); - } - if (!templateFile.isFile()) { - throw new BuildException("The Velocity template file ["+templateFile.getAbsolutePath()+"] is not a file."); - } - } - - if (null == projectHome) { - throw new BuildException("The "+this.getTaskName()+" task requires \"projectHome\" attribute."); - } - } - - class Generator extends AbstractGenerator { - @Override - protected void logDebug(String message) { - if (verbose) { - log(message); - } - } - - @Override - protected void logInfo(String message) { - log(message); - } - } - -} +package ca.uhn.fhir.tinder.ant; +/* + * #%L + * HAPI Tinder Plugin + * %% + * Copyright (C) 2014 - 2016 University Health Network + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.apache.commons.lang.WordUtils; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +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.AbstractGenerator; +import ca.uhn.fhir.tinder.AbstractGenerator.ExecutionException; +import ca.uhn.fhir.tinder.AbstractGenerator.FailureException; +import ca.uhn.fhir.tinder.GeneratorContext; +import ca.uhn.fhir.tinder.TinderStructuresMojo.ValueSetFileDefinition; +import ca.uhn.fhir.tinder.ValueSetGenerator; +import ca.uhn.fhir.tinder.VelocityHelper; +import ca.uhn.fhir.tinder.parser.BaseStructureParser; +import ca.uhn.fhir.tinder.parser.BaseStructureSpreadsheetParser; +import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet; +import ca.uhn.fhir.tinder.parser.TargetType; + +/** +/** + * Generate files from FHIR resource/composite metadata using Velocity templates. + *

+ * Generates either source or resource files for each selected resource or + * composite data type. One file is generated for each selected entity. The + * files are generated using a Velocity template that can be taken from + * inside the hapi-timder-plugin project or can be located in other projects + *

+ * The following Ant task properties are used + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
AttributeDescriptionRequired
versionThe FHIR version whose resource metadata + * is to be used to generate the files
+ * Valid values: dstu2 | dstu3 | r4
Yes
projectHomeThe project's base directory. This is used to + * possibly locate other assets within the project used in file generation.No. Defaults to: ${basedir}/..
generateResourcesShould files be generated from FHIR resource metadata?
+ * Valid values: true | false
At least one of these four options must be specified as true
generateDataTypesShould files be generated from FHIR composite data type metadata?
+ * Valid values: true | false
generateValueSetsShould files be generated from FHIR value set metadata?
+ * This option can only be used if generating multiple files (one file per value-set.)
+ * Valid values: true | false
generateProfilesShould files be generated from FHIR profile metadata?
+ * This option can only be used if generating multiple files (one file per profile.)
+ * Valid values: true | false
resourceSourceWhich source of resource definitions should be processed? Valid values are:
+ *
    + *
  • spreadsheet  to cause resources to be generated based on the FHIR spreadsheets
  • + *
  • model  to cause resources to be generated based on the model structure classes
No. Defaults to: spreadsheet
+ *
Java source files can be generated + * for FHIR resources or composite data types. Source files can be + * generated for each selected entity or a single source file can + * be generated containing all of the selected entity. The following configuration + * properties control the naming of the generated source files: + *

The following properties will be used when generating multiple source files:
+ *     <targetSourceDirectory>/<targetPackage>/<filenamePrefix>element-name<filenameSuffix>
+ *     where: element-name is the "title-case" name of the selected resource or composite data type. + *

The following properties will be used when generating a single source file:
+ *     <targetSourceDirectory>/<targetPackage>/<targetFile> + *

+ * Note that all dots in the targetPackage will be replaced by the path separator character when building the + * actual source file location. Also note that .java will be added to the filenameSuffix or targetFile if it is not already included. + *

targetSourceDirectoryThe source directory to contain the generated Java packages and classes.Yes when Java source files are to be generated
targetPackageThe Java package that will contain the generated classes. + * This package is generated in the <targetSourceDirectory> if needed.Yes when targetSourceDirectory is specified
packageBaseThe base Java package for related classes. This property + * can be used to reference class in other places in a folder structure.No
targetFileThe name of the file to be generatedYes when generating a single file containing all selected elements
filenamePrefixThe prefix string that is to be added onto the + * beginning of the resource or composite data type name to become + * the Java class name or resource file name.No
filenameSuffixSuffix that will be added onto the end of the resource + * or composite data type name to become the Java class name or resource file name.No.
+ *
Resource (non-Java) files can also be generated + * for FHIR resources or composite data types. a file can be + * generated for each selected entity or a single file can + * be generated containing all of the selected entity. The following configuration + * properties control the naming of the generated files: + *

The following properties will be used when generating multiple files (one for each selected element):
+ *     <targetResourceDirectory>/<targetFolder>/<filenamePrefix>element-name<filenameSuffix>
+ *     where: element-name is the "title-case" name of the selected resource or composite data type. + *

The following properties will be used when generating a single file containing all selected elements:
+ *     <targetResourceDirectory>/<targetFolder>/<targetFile> + *

targetResourceDirectoryThe resource directory to contain the generated files.Yes when resource files are to be generated
targetFolderThe folder within the targetResourceDirectory where the generated files will be placed. + * This folder is generated in the <targetResourceDirectory> if needed.No
+ *
templateThe path of one of the Velocity templates + * contained within the hapi-tinder-plugin Maven plug-in + * classpath that will be used to generate the files.One of these two options must be configured
templateFileThe full path to the Velocity template that is + * to be used to generate the files.
velocityPathWhen using the templateFile option, this property + * can be used to specify where Velocity macros and other resources are located.No. Defaults to same directory as the template file.
velocityPropertiesSpecifies the full path to a java properties file + * containing Velocity configuration propertiesNo.
includeResourcesA list of the names of the resources or composite data types that should + * be used in the file generationNo. Defaults to all defined resources except for DSTU2, + * the Binary resource is excluded and + * for DSTU3, the Conformance resource is excluded.
excludeResourcesA list of the names of the resources or composite data types that should + * excluded from the file generationNo.
valueSetFilesA list of files containing value-set resource definitions + * to be used.No. Defaults to all defined value-sets that + * are referenced from the selected resources.
profileFilesA list of files containing profile definitions + * to be used.No. Defaults to the default profile + * for each selected resource
+ * + * + * + * @author Bill Denton + * + */ +public class TinderGeneratorTask extends Task { + + private String version; + + private String projectHome; + + private boolean generateResources; + + private boolean generateDatatypes; + + private boolean generateValueSets; + + private boolean generateProfiles; + + private File targetSourceDirectory; + + private String targetPackage; + + private String packageBase; + + private String targetFile; + + private String filenamePrefix; + + private String filenameSuffix; + + private File targetResourceDirectory; + + private String targetFolder; + + // one of these two is required + private String template; + private File templateFile; + + private String velocityPath; + + private String velocityProperties; + + private List includeResources; + + private List excludeResources; + + private String resourceSource; + + private List valueSetFiles; + + private boolean verbose; + + private FhirContext fhirContext; // set from version in validateAttributes + + /** + * + */ + public TinderGeneratorTask () { + super(); + } + + protected void cleanup () { + } + + @Override + public void execute () throws BuildException { + validateAttributes(); + + + GeneratorContext context = new GeneratorContext(); + Generator generator = new Generator(); + try { + context.setVersion(version); + context.setBaseDir(projectHome); + context.setIncludeResources(includeResources); + context.setExcludeResources(excludeResources); + context.setResourceSource(resourceSource); + context.setValueSetFiles(valueSetFiles); + + generator.prepare(context); + } catch (ExecutionException e) { + throw new BuildException(e.getMessage(), e.getCause()); + } catch (FailureException e) { + throw new BuildException(e.getMessage(), e.getCause()); + } + + /* + * Deal with the generation target + */ + TargetType targetType = null; + File targetDirectory = null; + if (targetSourceDirectory != null) { + if (targetResourceDirectory != null) { + throw new BuildException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); + } + targetType = TargetType.SOURCE; + if (null == targetPackage) { + throw new BuildException("The [targetPackage] property must be specified when generating Java source code."); + } + targetDirectory = new File(targetSourceDirectory, targetPackage.replace('.', File.separatorChar)); + } else + if (targetResourceDirectory != null) { + if (targetSourceDirectory != null) { + throw new BuildException("Both [targetSourceDirectory] and [targetResourceDirectory] are specified. Please choose just one."); + } + targetType = TargetType.RESOURCE; + if (targetFolder != null) { + targetDirectory = new File(targetResourceDirectory, targetFolder); + } else { + targetDirectory = targetResourceDirectory; + } + if (null == targetPackage) { + targetPackage = ""; + } + } else { + throw new BuildException("Either [targetSourceDirectory] or [targetResourceDirectory] must be specified."); + } + targetDirectory.mkdirs(); + log(" * Output ["+targetType.toString()+"] Directory: " + targetDirectory.getAbsolutePath()); + + try { + /* + * Single file with all elements + */ + if (targetFile != null) { + if (targetType == TargetType.SOURCE) { + if (!targetFile.endsWith(".java")) { + targetFile += ".java"; + } + } + File target = new File(targetDirectory, targetFile); + OutputStreamWriter targetWriter = new OutputStreamWriter(new FileOutputStream(target, false), "UTF-8"); + + /* + * Next, deal with the template and initialize velocity + */ + VelocityEngine v = VelocityHelper.configureVelocityEngine(templateFile, velocityPath, velocityProperties); + InputStream templateIs = null; + if (templateFile != null) { + templateIs = new FileInputStream(templateFile); + } else { + templateIs = this.getClass().getResourceAsStream(template); + } + InputStreamReader templateReader = new InputStreamReader(templateIs); + + /* + * build new Velocity Context + */ + VelocityContext ctx = new VelocityContext(); + if (packageBase != null) { + ctx.put("packageBase", packageBase); + } else + if (targetPackage != null) { + int ix = targetPackage.lastIndexOf('.'); + if (ix > 0) { + ctx.put("packageBase", targetPackage.subSequence(0, ix)); + } else { + ctx.put("packageBase", targetPackage); + } + } + ctx.put("targetPackage", targetPackage); + ctx.put("targetFolder", targetFolder); + ctx.put("version", version); + ctx.put("isRi", BaseStructureSpreadsheetParser.determineVersionEnum(version).isRi()); + ctx.put("hash", "#"); + 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); + + /* + * Write resources if selected + */ + BaseStructureParser rp = context.getResourceGenerator(); + if (generateResources && rp != null) { + log("Writing Resources..."); + ctx.put("resources", rp.getResources()); + v.evaluate(ctx, targetWriter, "", templateReader); + targetWriter.close(); + } else { + DatatypeGeneratorUsingSpreadsheet dtp = context.getDatatypeGenerator(); + if (generateDatatypes && dtp != null) { + log("Writing DataTypes..."); + ctx.put("datatypes", dtp.getResources()); + v.evaluate(ctx, targetWriter, "", templateReader); + targetWriter.close(); + } + } + + /* + * Multiple files.. one for each element + */ + } else { + /* + * Write resources if selected + */ + BaseStructureParser rp = context.getResourceGenerator(); + if (generateResources && rp != null) { + log("Writing Resources..."); + rp.setFilenamePrefix(filenamePrefix); + rp.setFilenameSuffix(filenameSuffix); + rp.setTemplate(template); + rp.setTemplateFile(templateFile); + rp.setVelocityPath(velocityPath); + rp.setVelocityProperties(velocityProperties); + rp.writeAll(targetType, targetDirectory, null, targetPackage); + } + + /* + * Write composite datatypes + */ + DatatypeGeneratorUsingSpreadsheet dtp = context.getDatatypeGenerator(); + if (generateDatatypes && dtp != null) { + log("Writing Composite Datatypes..."); + dtp.setFilenamePrefix(filenamePrefix); + dtp.setFilenameSuffix(filenameSuffix); + dtp.setTemplate(template); + dtp.setTemplateFile(templateFile); + dtp.setVelocityPath(velocityPath); + dtp.setVelocityProperties(velocityProperties); + dtp.writeAll(targetType, targetDirectory, null, targetPackage); + } + + /* + * Write valuesets + */ + ValueSetGenerator vsp = context.getValueSetGenerator(); + if (generateValueSets && vsp != null) { + log("Writing ValueSet Enums..."); + vsp.setFilenamePrefix(filenamePrefix); + vsp.setFilenameSuffix(filenameSuffix); + vsp.setTemplate(template); + vsp.setTemplateFile(templateFile); + vsp.setVelocityPath(velocityPath); + vsp.setVelocityProperties(velocityProperties); + vsp.writeMarkedValueSets(targetType, targetDirectory, targetPackage); + } + + } + + } catch (Exception e) { + if (e instanceof BuildException) { + throw (BuildException)e; + } + log("Caught exception: "+e.getClass().getName()+" ["+e.getMessage()+"]", 1); + e.printStackTrace(); + throw new BuildException("Error processing "+getTaskName()+" task.", e); + } finally { + cleanup(); + } + } + + public void setExcludeResources(String names) { + if (null == this.excludeResources) { + this.excludeResources = new ArrayList(); + } + if (names != null) { + StringTokenizer tokens = new StringTokenizer(names, ", \t\r\n"); + while (tokens.hasMoreTokens()) { + String token = tokens.nextToken(); + this.excludeResources.add(token.trim()); + } + } + } + + public void setFilenamePrefix(String filenamePrefix) { + this.filenamePrefix = filenamePrefix; + } + + public void setFilenameSuffix(String filenameSuffix) { + this.filenameSuffix = filenameSuffix; + } + + public void setGenerateDatatypes(boolean generateDatatypes) { + this.generateDatatypes = generateDatatypes; + } + + public void setGenerateProfiles(boolean generateProfiles) { + this.generateProfiles = generateProfiles; + } + + public void setGenerateResources(boolean generateResources) { + this.generateResources = generateResources; + } + + public void setGenerateValueSets(boolean generateValueSets) { + this.generateValueSets = generateValueSets; + } + + public void setIncludeResources(String names) { + if (null == this.includeResources) { + this.includeResources = new ArrayList(); + } + if (names != null) { + StringTokenizer tokens = new StringTokenizer(names, ", \t\r\n"); + while (tokens.hasMoreTokens()) { + String token = tokens.nextToken(); + this.includeResources.add(token.trim()); + } + } + } + + public void setPackageBase(String packageBase) { + this.packageBase = packageBase; + } + + public void setProjectHome(String projectHome) { + this.projectHome = projectHome; + } + + public String getResourceSource() { + return resourceSource; + } + + public void setResourceSource(String resourceSource) { + this.resourceSource = resourceSource; + } + + public void setTargetFile(String targetFile) { + this.targetFile = targetFile; + } + + public void setTargetFolder(String targetFolder) { + this.targetFolder = targetFolder; + } + + public void setTargetPackage(String targetPackage) { + this.targetPackage = targetPackage; + } + + public void setTargetResourceDirectory(File targetResourceDirectory) { + this.targetResourceDirectory = targetResourceDirectory; + } + + public void setTargetSourceDirectory(File targetSourceDirectory) { + this.targetSourceDirectory = targetSourceDirectory; + } + + public void setTemplate(String template) { + this.template = template; + } + + public void setTemplateFile(File templateFile) { + this.templateFile = templateFile; + } + + public void setValueSetFiles(String names) { + if (null == this.valueSetFiles) { + this.valueSetFiles = new ArrayList(); + } + if (names != null) { + StringTokenizer tokens = new StringTokenizer(names, ", \t\r\n"); + while (tokens.hasMoreTokens()) { + String token = tokens.nextToken(); + ValueSetFileDefinition def = new ValueSetFileDefinition(); + def.setValueSetFile(token.trim()); + this.valueSetFiles.add(def); + } + } + } + + public void setVelocityPath(String velocityPath) { + this.velocityPath = velocityPath; + } + + public void setVelocityProperties(String velocityProperties) { + this.velocityProperties = velocityProperties; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + public void setVersion(String version) { + this.version = version; + } + + protected void validateAttributes () throws BuildException { + if (null == version) { + throw new BuildException("The "+this.getTaskName()+" task requires \"version\" attribute."); + } + if (null == template) { + if (null == templateFile) { + throw new BuildException("The "+this.getTaskName()+" task requires \"template\" or \"templateFile\" attribute."); + } + if (!templateFile.exists()) { + throw new BuildException("The Velocity template file ["+templateFile.getAbsolutePath()+"] does not exist."); + } + if (!templateFile.canRead()) { + throw new BuildException("The Velocity template file ["+templateFile.getAbsolutePath()+"] cannot be read."); + } + if (!templateFile.isFile()) { + throw new BuildException("The Velocity template file ["+templateFile.getAbsolutePath()+"] is not a file."); + } + } + + if (null == projectHome) { + throw new BuildException("The "+this.getTaskName()+" task requires \"projectHome\" attribute."); + } + } + + class Generator extends AbstractGenerator { + @Override + protected void logDebug(String message) { + if (verbose) { + log(message); + } + } + + @Override + protected void logInfo(String message) { + log(message); + } + } + +}