package ca.uhn.fhir.tinder;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.util.Collection;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.instance.model.DomainResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.method.MethodUtil;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
@Mojo(name = "minimize-resources", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class ResourceMinimizerMojo extends AbstractMojo {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceMinimizerMojo.class);
@Parameter(required = true)
private String fhirVersion;
private long myByteCount;
private FhirContext myCtx;
private int myFileCount;
@Parameter(required = true)
private File targetDirectory;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
ourLog.info("Starting resource minimizer");
if (myCtx != null) {
// nothing
} else if ("DSTU".equals(fhirVersion)) {
myCtx = FhirContext.forDstu1();
} else if ("DSTU2".equals(fhirVersion)) {
myCtx = FhirContext.forDstu2();
} else if ("HL7ORG_DSTU2".equals(fhirVersion)) {
myCtx = FhirContext.forDstu2Hl7Org();
} else if ("DSTU2_1".equals(fhirVersion)) {
myCtx = FhirContext.forDstu2_1();
} else if ("DSTU3".equals(fhirVersion)) {
myCtx = FhirContext.forDstu3();
} else {
throw new MojoFailureException("Unknown version: " + fhirVersion);
}
ourLog.info("Looking for files in directory: {}", targetDirectory.getAbsolutePath());
Collection<File> files = FileUtils.listFiles(targetDirectory, new String[] { "xml", "json" }, true);
for (File nextFile : files) {
ourLog.debug("Checking file: {}", nextFile);
String inputString;
try {
inputString = IOUtils.toString(new FileInputStream(nextFile), "UTF-8");
} catch (IOException e) {
throw new MojoFailureException("Failed to read file: " + nextFile, e);
}
IParser parser = MethodUtil.detectEncoding(inputString).newParser(myCtx);
IBaseResource input = parser.parseResource(inputString);
if (input instanceof IResource) {
((IResource) input).getText().getDiv().setValueAsString((String) null);
((IResource) input).getText().getStatus().setValueAsString((String) null);
if (input instanceof Bundle) {
for (Entry nextEntry : ((Bundle) input).getEntry()) {
if (nextEntry.getResource() != null) {
nextEntry.getResource().getText().getDiv().setValueAsString((String) null);
nextEntry.getResource().getText().getStatus().setValueAsString((String) null);
}
}
}
} else if (input instanceof org.hl7.fhir.dstu3.model.Bundle) {
for (org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent nextEntry : ((org.hl7.fhir.dstu3.model.Bundle) input).getEntry()) {
if (nextEntry.getResource() instanceof org.hl7.fhir.dstu3.model.DomainResource) {
((org.hl7.fhir.dstu3.model.DomainResource) nextEntry.getResource()).getText().getDiv().setValueAsString((String) null);
((org.hl7.fhir.dstu3.model.DomainResource) nextEntry.getResource()).getText().getStatusElement().setValueAsString((String) null);
}
}
} else if (input instanceof org.hl7.fhir.dstu2016may.model.Bundle) {
for (org.hl7.fhir.dstu2016may.model.Bundle.BundleEntryComponent nextEntry : ((org.hl7.fhir.dstu2016may.model.Bundle) input).getEntry()) {
if (nextEntry.getResource() instanceof org.hl7.fhir.dstu2016may.model.DomainResource) {
((org.hl7.fhir.dstu2016may.model.DomainResource) nextEntry.getResource()).getText().getDiv().setValueAsString((String) null);
((org.hl7.fhir.dstu2016may.model.DomainResource) nextEntry.getResource()).getText().getStatusElement().setValueAsString((String) null);
}
}
} else if (input instanceof org.hl7.fhir.dstu3.model.DomainResource) {
try {
((org.hl7.fhir.dstu3.model.DomainResource) input).getText().setDivAsString(null);
((org.hl7.fhir.dstu3.model.DomainResource) input).getText().getStatusElement().setValueAsString(null);
} catch (Exception e) {
ourLog.error("Failed to clear narrative", e);
}
} else {
ourLog.info("Ignoring type: " + input.getClass());
continue;
}
String outputString = parser.setPrettyPrint(true).encodeResourceToString(input);
StringBuilder b = new StringBuilder();
for (String nextLine : outputString.split("\\n")) {
int i;
for (i = 0; i < nextLine.length(); i++) {
if (nextLine.charAt(i) != ' ') {
break;
}
}
b.append(StringUtils.leftPad("", i / 3, ' '));
b.append(nextLine.substring(i));
b.append("\n");
}
outputString = b.toString();
if (!inputString.equals(outputString)) {
ourLog.info("Trimming contents of resource: {} - From {} to {}", nextFile, FileUtils.byteCountToDisplaySize(inputString.length()), FileUtils.byteCountToDisplaySize(outputString.length()));
myByteCount += (inputString.length() - outputString.length());
myFileCount++;
try {
String f = nextFile.getAbsolutePath();
Writer w = new OutputStreamWriter(new FileOutputStream(f, false), "UTF-8");
w = new BufferedWriter(w);
w.append(outputString);
w.close();
} catch (IOException e) {
throw new MojoFailureException("Failed to write " + nextFile, e);
}
}
}
}
public long getByteCount() {
return myByteCount;
}
public int getFileCount() {
return myFileCount;
}
public static void main(String[] args) throws Exception {
FhirContext ctxDstu2 = FhirContext.forDstu2();
FhirContext ctxDstu2_1 = FhirContext.forDstu2_1();
FhirContext ctxDstu3 = FhirContext.forDstu3();
LoggerContext loggerContext = ((ch.qos.logback.classic.Logger) ourLog).getLoggerContext();
URL mainURL = ConfigurationWatchListUtil.getMainWatchURL(loggerContext);
System.out.println(mainURL);
// or even
ourLog.info("Logback used '{}' as the configuration file.", mainURL);
int fileCount = 0;
long byteCount = 0;
ResourceMinimizerMojo m = new ResourceMinimizerMojo();
// m.myCtx = ctxDstu2;
// m.targetDirectory = new File("../hapi-tinder-plugin/src/main/resources/vs/dstu2");
// m.fhirVersion = "DSTU2";
// m.execute();
// byteCount += m.getByteCount();
// fileCount += m.getFileCount();
//
// m = new ResourceMinimizerMojo();
// m.myCtx = ctxDstu2;
// m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu2/src/main/resources/org/hl7/fhir/instance/model/valueset");
// m.fhirVersion = "DSTU2";
// m.execute();
// byteCount += m.getByteCount();
// fileCount += m.getFileCount();
//
// m = new ResourceMinimizerMojo();
// m.myCtx = ctxDstu2;
// m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu2/src/main/resources/org/hl7/fhir/instance/model/profile");
// m.fhirVersion = "DSTU2";
// m.execute();
// byteCount += m.getByteCount();
// fileCount += m.getFileCount();
m = new ResourceMinimizerMojo();
m.myCtx = ctxDstu3;
m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/instance/model/dstu3/profile");
m.fhirVersion = "DSTU3";
m.execute();
byteCount += m.getByteCount();
fileCount += m.getFileCount();
m = new ResourceMinimizerMojo();
m.myCtx = ctxDstu3;
m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/instance/model/dstu3/valueset");
m.fhirVersion = "DSTU3";
m.execute();
byteCount += m.getByteCount();
fileCount += m.getFileCount();
// m = new ResourceMinimizerMojo();
// m.myCtx = ctxDstu2_1;
// m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/profile");
// m.fhirVersion = "DSTU2_1";
// m.execute();
// byteCount += m.getByteCount();
// fileCount += m.getFileCount();
//
// m = new ResourceMinimizerMojo();
// m.myCtx = ctxDstu2_1;
// m.targetDirectory = new File("../hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/valueset");
// m.fhirVersion = "DSTU2_1";
// m.execute();
// byteCount += m.getByteCount();
// fileCount += m.getFileCount();
ourLog.info("Trimmed {} files", fileCount);
ourLog.info("Trimmed {} bytes", FileUtils.byteCountToDisplaySize(byteCount));
}
}