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.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeSet;
import org.apache.maven.plugin.MojoFailureException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.tinder.GeneratorContext.ProfileFileDefinition;
import ca.uhn.fhir.tinder.parser.DatatypeGeneratorUsingSpreadsheet;
import ca.uhn.fhir.tinder.parser.ProfileParser;
import ca.uhn.fhir.tinder.parser.ResourceGeneratorUsingSpreadsheet;
public abstract class AbstractGenerator {
protected abstract void logInfo (String message);
protected abstract void logDebug (String message);
public void prepare (GeneratorContext context) throws ExecutionException, FailureException {
/*
* Deal with the FHIR spec version
*/
FhirContext fhirContext;
String packageSuffix = "";
if ("dstu".equals(context.getVersion())) {
fhirContext = FhirContext.forDstu1();
} else 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<String> includeResources = context.getIncludeResources();
List<String> excludeResources = context.getExcludeResources();
if (includeResources == null || includeResources.isEmpty()) {
includeResources = new ArrayList<String>();
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<String> keys = new TreeSet<String>();
for(Object next : p.keySet()) {
keys.add((String) next);
}
for (String next : keys) {
if (next.startsWith("resource.")) {
includeResources.add(next.substring("resource.".length()).toLowerCase());
}
}
/*
* No spreadsheet existed for Binary in DSTU1 so we don't generate it.. this
* is something we could work around, but at this point why bother since it's
* only an issue for DSTU1
*/
if (fhirContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
includeResources.remove("binary");
}
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;
ProfileParser pp = null;
Map<String, String> datatypeLocalImports = new HashMap<String, String>();
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);
if (context.getProfileFiles() != null) {
logInfo("Loading profiles...");
pp = new ProfileParser(context.getVersion(), context.getBaseDir());
context.setProfileParser(pp);
for (ProfileFileDefinition next : context.getProfileFiles()) {
logInfo("Parsing file: "+next.profileFile);
try {
pp.parseSingleProfile(new File(next.profileFile), next.profileSourceUrl);
} catch (MojoFailureException e) {
throw new FailureException(e);
}
}
pp.bindValueSets(vsp);
pp.markResourcesForImports();
pp.getLocalImports().putAll(datatypeLocalImports);
datatypeLocalImports.putAll(pp.getLocalImports());
pp.combineContentMaps(rp);
pp.combineContentMaps(dtp);
dtp.combineContentMaps(pp);
}
}
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);
}
}
}