diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/IGKnowledgeProvider.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/IGKnowledgeProvider.java index cc5023125..a8ceabe17 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/IGKnowledgeProvider.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/IGKnowledgeProvider.java @@ -448,12 +448,13 @@ else if (pathPattern != null) bc.setWebPath(r.fhirType()+"/"+r.getId()+".html"); r.getElement().setWebPath(bc.getWebPath()); for (Resource cont : bc.getContained()) { - if (base != null) + if (base != null) { cont.setWebPath(doReplacements(base, r, cont, null, null, bc.getId()+"_")); - else if (pathPattern != null) + } else if (pathPattern != null) { cont.setWebPath(pathPattern.replace("[type]", r.fhirType()).replace("[id]", bc.getId()+"_"+cont.getId())); - else + } else { cont.setWebPath(r.fhirType()+"/"+bc.getId()+"_"+r.getId()+".html"); + } } } diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/IGPublisherHostServices.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/IGPublisherHostServices.java new file mode 100644 index 000000000..1c77873cb --- /dev/null +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/IGPublisherHostServices.java @@ -0,0 +1,140 @@ +package org.hl7.fhir.igtools.publisher; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.NotImplementedException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.PathEngineException; +import org.hl7.fhir.r5.context.SimpleWorkerContext; +import org.hl7.fhir.r5.fhirpath.FHIRPathEngine; +import org.hl7.fhir.r5.fhirpath.TypeDetails; +import org.hl7.fhir.r5.liquid.GlobalObject; +import org.hl7.fhir.r5.fhirpath.ExpressionNode.CollectionStatus; +import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext; +import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails; +import org.hl7.fhir.r5.model.Base; +import org.hl7.fhir.r5.model.DateTimeType; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.r5.utils.validation.IResourceValidator; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.validation.ValidationMessage; + +public class IGPublisherHostServices implements IEvaluationContext { + + + private IGKnowledgeProvider igpkp; + private List fileList = new ArrayList(); + private SimpleWorkerContext context; + private DateTimeType dt; + private StringType pathToSpec; + private Map functions = new HashMap<>(); + + public IGPublisherHostServices(IGKnowledgeProvider igpkp, List fileList, + SimpleWorkerContext context, DateTimeType dt, StringType pathToSpec) { + super(); + this.igpkp = igpkp; + this.fileList = fileList; + this.context = context; + this.dt = dt; + this.pathToSpec = pathToSpec; + } + + public IGPublisherHostServices registerFunction(FunctionDefinition function) { + functions.put(function.name(), function); + return this; + } + + @Override + public List resolveConstant(FHIRPathEngine engine, Object appContext, String name, boolean beforeContext, boolean explicitConstant) throws PathEngineException { + if ("Globals".equals(name)) { + List list = new ArrayList(); + list.add(new GlobalObject(dt, pathToSpec)); + return list; + } else { + return new ArrayList<>(); + } + } + + @Override + public TypeDetails resolveConstantType(FHIRPathEngine engine, Object appContext, String name, boolean explicitConstant) throws PathEngineException { + if ("Globals".equals(name)) { + return new TypeDetails(CollectionStatus.SINGLETON, "GlobalObject"); + } else { + return null; // whatever it is, we don't know about it. + } + } + + @Override + public boolean paramIsType(String name, int index) { + return false; + } + + @Override + public boolean log(String argument, List focus) { + return false; + } + + @Override + public FunctionDetails resolveFunction(FHIRPathEngine engine, String functionName) { + FunctionDefinition fd = functions.get(functionName); + return fd == null ? null : fd.details(); + } + + @Override + public TypeDetails checkFunction(FHIRPathEngine engine, Object appContext, String functionName, TypeDetails focus, List parameters) throws PathEngineException { + FunctionDefinition fd = functions.get(functionName); + return fd == null ? null : fd.check(engine, appContext, focus, parameters); + } + + @Override + public List executeFunction(FHIRPathEngine engine, Object appContext, List focus, String functionName, List> parameters) { + FunctionDefinition fd = functions.get(functionName); + return fd == null ? null : fd.execute(engine, appContext, focus, parameters); + } + + @Override + public Base resolveReference(FHIRPathEngine engine, Object appContext, String url, Base refContext) { + if (Utilities.isAbsoluteUrl(url)) { + if (url.startsWith(igpkp.getCanonical())) { + url = url.substring(igpkp.getCanonical().length()); + if (url.startsWith("/")) { + url = url.substring(1); + } + } else + return null;; + } + for (FetchedFile f : fileList) { + for (FetchedResource r : f.getResources()) { + if (r.getElement() != null && url.equals(r.fhirType()+"/"+r.getId())) { + return r.getElement(); + } + } + } + return null; + } + + @Override + public boolean conformsToProfile(FHIRPathEngine engine, Object appContext, Base item, String url) throws FHIRException { + IResourceValidator val = context.newValidator(); + List valerrors = new ArrayList(); + if (item instanceof Resource) { + val.validate(appContext, valerrors, (Resource) item, url); + boolean ok = true; + for (ValidationMessage v : valerrors) { + ok = ok && v.getLevel().isError(); + } + return ok; + } + throw new NotImplementedException("Not done yet (IGPublisherHostServices.conformsToProfile), when item is element"); + } + + @Override + public ValueSet resolveValueSet(FHIRPathEngine engine, Object appContext, String url) { + throw new NotImplementedException("Not done yet (IGPublisherHostServices.resolveValueSet)"); // cause I don't know when we 'd need to do this + } +} \ No newline at end of file diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/Publisher.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/Publisher.java index 166f3ed7f..8a191fe07 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/Publisher.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/Publisher.java @@ -91,7 +91,6 @@ import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.igtools.publisher.FetchedFile.FetchedBundleType; import org.hl7.fhir.igtools.publisher.IFetchFile.FetchState; import org.hl7.fhir.igtools.publisher.comparators.IpaComparator; @@ -164,10 +163,11 @@ import org.hl7.fhir.r5.elementmodel.ParserBase.ValidationPolicy; import org.hl7.fhir.r5.fhirpath.ExpressionNode; import org.hl7.fhir.r5.fhirpath.FHIRPathEngine; -import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext; -import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails; -import org.hl7.fhir.r5.fhirpath.TypeDetails; import org.hl7.fhir.r5.formats.IParser.OutputStyle; +import org.hl7.fhir.r5.liquid.BaseJsonWrapper; +import org.hl7.fhir.r5.liquid.GlobalObject.GlobalObjectRandomFunction; +import org.hl7.fhir.r5.liquid.LiquidEngine; +import org.hl7.fhir.r5.liquid.LiquidEngine.LiquidDocument; import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.formats.RdfParser; import org.hl7.fhir.r5.formats.XmlParser; @@ -299,8 +299,8 @@ import org.hl7.fhir.r5.terminologies.ValueSetUtilities; import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome; import org.hl7.fhir.r5.terminologies.utilities.ValidationResult; +import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.r5.utils.EOperationOutcome; -import org.hl7.fhir.r5.utils.LiquidEngine; import org.hl7.fhir.r5.utils.MappingSheetParser; import org.hl7.fhir.r5.utils.NPMPackageGenerator; import org.hl7.fhir.r5.utils.NPMPackageGenerator.Category; @@ -314,7 +314,6 @@ import org.hl7.fhir.r5.utils.formats.CSVWriter; import org.hl7.fhir.r5.utils.structuremap.StructureMapAnalysis; import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities; -import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IValidationProfileUsageTracker; import org.hl7.fhir.r5.utils.validation.ValidatorSession; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; @@ -536,85 +535,6 @@ public String getVersion() { } - public class IGPublisherHostServices implements IEvaluationContext { - - @Override - public List resolveConstant(FHIRPathEngine engine, Object appContext, String name, boolean beforeContext, boolean explicitConstant) throws PathEngineException { - return new ArrayList<>(); - } - - @Override - public TypeDetails resolveConstantType(FHIRPathEngine engine, Object appContext, String name, boolean explicitConstant) throws PathEngineException { - return null; // whatever it is, we don't know about it. - } - - @Override - public boolean paramIsType(String name, int index) { - return false; - } - - @Override - public boolean log(String argument, List focus) { - return false; - } - - @Override - public FunctionDetails resolveFunction(FHIRPathEngine engine, String functionName) { - throw new NotImplementedException("Not done yet (IGPublisherHostServices.resolveFunction)"); - } - - @Override - public TypeDetails checkFunction(FHIRPathEngine engine, Object appContext, String functionName, TypeDetails focus, List parameters) throws PathEngineException { - throw new NotImplementedException("Not done yet (IGPublisherHostServices.checkFunction)"); - } - - @Override - public List executeFunction(FHIRPathEngine engine, Object appContext, List focus, String functionName, List> parameters) { - throw new NotImplementedException("Not done yet (IGPublisherHostServices.executeFunction)"); - } - - @Override - public Base resolveReference(FHIRPathEngine engine, Object appContext, String url, Base refContext) { - if (Utilities.isAbsoluteUrl(url)) { - if (url.startsWith(igpkp.getCanonical())) { - url = url.substring(igpkp.getCanonical().length()); - if (url.startsWith("/")) { - url = url.substring(1); - } - } else - return null;; - } - for (FetchedFile f : fileList) { - for (FetchedResource r : f.getResources()) { - if (r.getElement() != null && url.equals(r.fhirType()+"/"+r.getId())) { - return r.getElement(); - } - } - } - return null; - } - - @Override - public boolean conformsToProfile(FHIRPathEngine engine, Object appContext, Base item, String url) throws FHIRException { - IResourceValidator val = context.newValidator(); - List valerrors = new ArrayList(); - if (item instanceof Resource) { - val.validate(appContext, valerrors, (Resource) item, url); - boolean ok = true; - for (ValidationMessage v : valerrors) { - ok = ok && v.getLevel().isError(); - } - return ok; - } - throw new NotImplementedException("Not done yet (IGPublisherHostServices.conformsToProfile), when item is element"); - } - - @Override - public ValueSet resolveValueSet(FHIRPathEngine engine, Object appContext, String url) { - throw new NotImplementedException("Not done yet (IGPublisherHostServices.resolveValueSet)"); // cause I don't know when we 'd need to do this - } - } - public class TypeParserR2 implements ITypeParser { @Override @@ -2842,6 +2762,7 @@ private void initializeFromIg(IniFile ini) throws Exception { copyrightYear = null; Boolean useStatsOptOut = null; List extensionDomains = new ArrayList<>(); + List factories = new ArrayList<>(); tempDir = Utilities.path(rootDir, "temp"); tempLangDir = Utilities.path(rootDir, "translations"); outputDir = Utilities.path(rootDir, "output"); @@ -3170,6 +3091,9 @@ else if (p.getValue().equals("no-experimental-content")) case "viewDefinition": viewDefinitions.add(p.getValue()); break; + case "test-data-factory": + factories.add(p.getValue()); + break; case "fixed-value-format": fixedFormat = FixedValueFormat.fromCode(p.getValue()); break; @@ -3429,7 +3353,10 @@ else if (vsCache == null) { // set up validator; validatorSession = new ValidatorSession(); - validator = new InstanceValidator(context, new IGPublisherHostServices(), context.getXVer(), validatorSession); // todo: host services for reference resolution.... + IGPublisherHostServices hs = new IGPublisherHostServices(igpkp, fileList, context, new DateTimeType(execTime), new StringType(igpkp.specPath())); + hs.registerFunction(new GlobalObjectRandomFunction()); + hs.registerFunction(new TestDataFactory.DataLookupFunction()); + validator = new InstanceValidator(context, hs, context.getXVer(), validatorSession); // todo: host services for reference resolution.... validator.setAllowXsiLocation(true); validator.setNoBindingMsgSuppressed(true); validator.setNoExtensibleWarnings(!allowExtensibleWarnings); @@ -3503,6 +3430,14 @@ else if (useStatsOptOut != null) else extensionTracker.setoptIn(!ini.getBooleanProperty("IG", "usage-stats-opt-out")); + if (!factories.isEmpty()) { + LiquidEngine liquid = new LiquidEngine(context, validator.getExternalHostServices()); + for (String f : factories) { + TestDataFactory tdf = new TestDataFactory(Utilities.getDirectoryForFile(configFile), f, liquid); + log("Execute Test Data Factory '"+tdf.getName()+"'"); + tdf.execute(); + } + } log("Initialization complete"); } @@ -7630,12 +7565,12 @@ private void checkOIDsUnique() { if (oids.isEmpty()) { if (Utilities.existsInList(r.getResource().fhirType(), "CodeSystem", "ValueSet")) { if (forHL7orFHIR()) { - f.getErrors().add(new ValidationMessage(Source.Publisher, IssueType.BUSINESSRULE, "Resource", "This resource must have an OID assigned to cater for possible use with OID based terminology systems e.g. CDA usage"+oidHint, IssueSeverity.ERROR)); + f.getErrors().add(new ValidationMessage(Source.Publisher, IssueType.BUSINESSRULE, "Resource", "The resource "+r.fhirType()+"/"+r.getId()+" must have an OID assigned to cater for possible use with OID based terminology systems e.g. CDA usage"+oidHint, IssueSeverity.ERROR)); } else { - f.getErrors().add(new ValidationMessage(Source.Publisher, IssueType.BUSINESSRULE, "Resource", "This resource should have an OID assigned to cater for possible use with OID based terminology systems e.g. CDA usage"+oidHint, IssueSeverity.WARNING)); + f.getErrors().add(new ValidationMessage(Source.Publisher, IssueType.BUSINESSRULE, "Resource", "The resource "+r.fhirType()+"/"+r.getId()+" should have an OID assigned to cater for possible use with OID based terminology systems e.g. CDA usage"+oidHint, IssueSeverity.WARNING)); } } else { - f.getErrors().add(new ValidationMessage(Source.Publisher, IssueType.BUSINESSRULE, "Resource", "This resource could usefully have an OID assigned"+oidHint, IssueSeverity.INFORMATION)); + f.getErrors().add(new ValidationMessage(Source.Publisher, IssueType.BUSINESSRULE, "Resource", "The resource "+r.fhirType()+"/"+r.getId()+" could usefully have an OID assigned"+oidHint, IssueSeverity.INFORMATION)); } } else { for (String oid : oids) { @@ -10869,7 +10804,9 @@ private void generateResourceReferences() throws Exception { } } for (String rt : resourceTypes) { - generateResourceReferences(rt); + if (!rt.contains(":")) { + generateResourceReferences(rt); + } } generateProfiles(); generateExtensions(); @@ -11541,7 +11478,7 @@ private byte[] processCustomLiquid(DBBuilder db, byte[] content, FetchedFile f) try { String src = new String(content); boolean changed = false; - String[] keywords = {"sql", "fragment"}; + String[] keywords = {"sql", "fragment", "json"}; for (String keyword: Arrays.asList(keywords)) { while (db != null && src.contains("{% " + keyword)) { @@ -11566,6 +11503,14 @@ private byte[] processCustomLiquid(DBBuilder db, byte[] content, FetchedFile f) case "fragment": substitute = processFragment(arguments, f); + break; + + case "json": + substitute = processJson(arguments, f); + break; + + default: + throw new FHIRException("Internal Error - unkonwn keyword "+keyword); } src = pfx + substitute + sfx; @@ -11680,6 +11625,29 @@ private String processSQLCommand(DBBuilder db, String src, FetchedFile f) throws return "{% include sql-"+i+"-fragment.xhtml %}"; } + private String processJson(String arguments, FetchedFile f) throws FHIRException, IOException { + long start = System.currentTimeMillis(); + String cnt = null; + try { + String args = arguments.trim(); + File src = new File(Utilities.path(Utilities.getDirectoryForFile(configFile), args.substring(0, args.indexOf(" ")).trim())); + File tsrc = new File(Utilities.path(Utilities.getDirectoryForFile(configFile), args.substring(args.indexOf(" ")+1).trim())); + + JsonObject json = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(src); + LiquidEngine liquid = new LiquidEngine(context, rc.getServices()); + LiquidDocument template = liquid.parse(TextFile.fileToString(tsrc), tsrc.getAbsolutePath()); + BaseJsonWrapper base = new BaseJsonWrapper(json); + cnt = liquid.evaluate(template, base, this).trim(); + } catch (Exception e) { + XhtmlNode p = new XhtmlNode(NodeType.Element, "p"); + p.tx(e.getMessage()); + cnt = new XhtmlComposer(false, true).compose(p); + } + int i = sqlIndex++; + fragment("json-"+i+"-fragment", "\r\n"+cnt, f.getOutputNames(), start, "json", "page"); + return "{% include json-"+i+"-fragment.xhtml %}"; + } + private String processFragment(String arguments, FetchedFile f) throws FHIRException { int firstSpace = arguments.indexOf(" "); int secondSpace = arguments.indexOf(" ",firstSpace + 1); @@ -13799,6 +13767,7 @@ public static void main(String[] args) throws Exception { org.hl7.fhir.utilities.FileFormat.checkCharsetAndWarnIfNotUTF8(System.out); NpmPackage.setLoadCustomResources(true); + ManagedWebAccess.loadFromFHIRSettings(); if (CliParams.hasNamedParam(args, FHIR_SETTINGS_PARAM)) { FhirSettings.setExplicitFilePath(CliParams.getNamedParam(args, FHIR_SETTINGS_PARAM)); diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/TestDataFactory.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/TestDataFactory.java new file mode 100644 index 000000000..584999628 --- /dev/null +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/TestDataFactory.java @@ -0,0 +1,206 @@ +package org.hl7.fhir.igtools.publisher; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r5.fhirpath.ExpressionNode.CollectionStatus; +import org.hl7.fhir.r5.fhirpath.FHIRPathEngine; +import org.hl7.fhir.r5.fhirpath.FHIRPathEngine.IEvaluationContext.FunctionDefinition; +import org.hl7.fhir.r5.fhirpath.FHIRPathUtilityClasses.FunctionDetails; +import org.hl7.fhir.r5.fhirpath.TypeDetails; +import org.hl7.fhir.r5.liquid.BaseCSVWrapper; +import org.hl7.fhir.r5.liquid.LiquidEngine; +import org.hl7.fhir.r5.liquid.LiquidEngine.LiquidDocument; +import org.hl7.fhir.r5.model.Base; +import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.utilities.CSVReader; +import org.hl7.fhir.utilities.FhirPublication; +import org.hl7.fhir.utilities.IniFile; +import org.hl7.fhir.utilities.TextFile; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.json.JsonException; +import org.hl7.fhir.utilities.json.model.JsonObject; +import org.hl7.fhir.utilities.json.parser.JsonParser; + +public class TestDataFactory { + + public static class DataTable extends Base { + List columns = new ArrayList(); + List> rows = new ArrayList>(); + + @Override + public String fhirType() { + return "DataTable"; + } + @Override + public String getIdBase() { + return null; + } + @Override + public void setIdBase(String value) { + throw new Error("Readonly"); + } + @Override + public Base copy() { + return this; + } + + @Override + public FhirPublication getFHIRPublicationVersion() { + return FhirPublication.R5; + } + + public String cell(int row, String col) { + if (row >= 0 && row < rows.size()) { + List r = rows.get(row); + int c = -1; + if (Utilities.isInteger(col)) { + c = Utilities.parseInt(col, -1); + } else { + c = columns.indexOf(col); + } + if (c > -1 && c < r.size()) { + return r.get(c); + } + } + return null; + } + } + + public static class DataLookupFunction extends FunctionDefinition { + + @Override + public String name() { + return "cell"; + } + + @Override + public FunctionDetails details() { + return new FunctionDetails("Lookup a data element", 2, 2); + } + + @Override + public TypeDetails check(FHIRPathEngine engine, Object appContext, TypeDetails focus, List parameters) { + return new TypeDetails(CollectionStatus.SINGLETON, "string"); + } + + @Override + public List execute(FHIRPathEngine engine, Object appContext, List focus, List> parameters) { + int row = Utilities.parseInt(parameters.get(0).get(0).primitiveValue(), 0); + String col = parameters.get(1).get(0).primitiveValue(); + DataTable dt = (DataTable) focus.get(0); + + List res = new ArrayList(); + String s = dt.cell(row, col); + if (!Utilities.noString(s)) { + res.add(new StringType(s)); + } + return res; + } + + } + private String rootFolder; + private LiquidEngine liquid; + private IniFile ini; + + protected TestDataFactory(String rootFolder, String iniFile, LiquidEngine liquid) throws IOException { + super(); + this.rootFolder = rootFolder; + ini = new IniFile(Utilities.path(rootFolder, iniFile)); + this.liquid = liquid; + } + + public String getName() { + return ini.getStringProperty("factory", "name"); + } + + public void execute() throws FHIRException, IOException { + try { + LiquidDocument template = liquid.parse(TextFile.fileToString(Utilities.path(rootFolder, ini.getStringProperty("factory", "liquid"))), "liquid"); + DataTable dt = loadData(Utilities.path(rootFolder, ini.getStringProperty("factory", "data"))); + liquid.getVars().clear(); + if (ini.hasSection("tables")) { + for (String n : ini.getPropertyNames("tables")) { + liquid.getVars().put(n, loadData(Utilities.path(rootFolder, ini.getStringProperty("tables", n)))); + } + } + String format = ini.getStringProperty("factory", "format"); + if ("bundle".equals(ini.getStringProperty("factory", "mode"))) { + byte[] data = runBundle(template, dt.columns, dt.rows, format); + TextFile.bytesToFile(data, Utilities.path(rootFolder, ini.getStringProperty("factory", "output"), ini.getStringProperty("factory", "filename"))); + } else { + for (List row : dt.rows) { + byte[] data = runInstance(template, dt.columns, row, format); + TextFile.bytesToFile(data, Utilities.path(rootFolder, ini.getStringProperty("factory", "output"), + getFileName(ini.getStringProperty("factory", "filename"), dt.columns, row))); + } + } + } catch (Exception e) { + System.out.println("Error running test case '"+getName()+"': "+e.getMessage()); + e.printStackTrace(); + throw e; + } + } + + private String getFileName(String name, List columns, List values) { + for (int i = 0; i < columns.size(); i++) { + name = name.replace("{{"+columns.get(i)+"}}", values.get(i)); + } + return name; + } + + private byte[] runInstance(LiquidDocument template, List columns, List row, String format) throws JsonException, IOException { + BaseCSVWrapper base = BaseCSVWrapper.forRow(columns, row); + String cnt = liquid.evaluate(template, base, this).trim(); + if ("json".equals(format)) { + JsonObject j = JsonParser.parseObject(cnt, true); + return JsonParser.composeBytes(j, true); + } else { + throw new Error("Format "+format+" not supported at this time."); + } + } + + private byte[] runBundle(LiquidDocument template, List columns, List> rows, String format) throws JsonException, IOException { + BaseCSVWrapper base = BaseCSVWrapper.forRows(columns, rows); + String cnt = liquid.evaluate(template, base, this).trim(); + TextFile.stringToFile(cnt, "/Users/grahamegrieve/temp/liquid.out.json"); + if ("json".equals(format)) { + JsonObject j = JsonParser.parseObject(cnt, true); + return JsonParser.composeBytes(j, true); + } else { + throw new Error("Format "+format+" not supported at this time."); + } + } + + private DataTable loadData(String path) throws FHIRException, IOException { + DataTable dt = new DataTable(); + CSVReader csv = new CSVReader(new FileInputStream(path)); + dt.columns.add("counter"); + for (String n : csv.parseLine()) { + dt.columns.add(n); + } + int t = dt.columns.size(); + int c = 0; + while (csv.ready()) { + c++; + List values = new ArrayList(); + values.add(""+c); + for (String b : csv.parseLine()) { + values.add(b); + } + while (values.size() < t) { + values.add(""); + } + while (values.size() > t) { + values.remove(values.size()-1); + } + dt.rows.add(values); + } + return dt; + } +} diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/ImposesComparator.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/ImposesComparator.java index 500068f6d..f5d660939 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/ImposesComparator.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/ImposesComparator.java @@ -233,7 +233,11 @@ public void finishChecks() throws IOException { Utilities.createDirectory(Utilities.path(dstDir, "ipa-comparison-v"+vi.version)); ComparisonRenderer cr = new ComparisonRenderer(vi.context, context, Utilities.path(dstDir, "ipa-comparison-v"+vi.version), session); cr.getTemplates().put("CodeSystem", new String(context.getBinaryForKey("template-comparison-CodeSystem.html"))); + cr.getTemplates().put("CodeSystem-Union", new String(context.getBinaryForKey("template-comparison-CodeSystem-Union.html"))); + cr.getTemplates().put("CodeSystem-Intersection", new String(context.getBinaryForKey("template-comparison-CodeSystem-Intersection.html"))); cr.getTemplates().put("ValueSet", new String(context.getBinaryForKey("template-comparison-ValueSet.html"))); + cr.getTemplates().put("ValueSet-Union", new String(context.getBinaryForKey("template-comparison-ValueSet-Union.html"))); + cr.getTemplates().put("ValueSet-Intersection", new String(context.getBinaryForKey("template-comparison-ValueSet-Intersection.html"))); cr.getTemplates().put("Profile", new String(context.getBinaryForKey("template-comparison-Profile.html"))); cr.getTemplates().put("Profile-Union", new String(context.getBinaryForKey("template-comparison-Profile-Union.html"))); cr.getTemplates().put("Profile-Intersection", new String(context.getBinaryForKey("template-comparison-Profile-Intersection.html"))); diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/IpaComparator.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/IpaComparator.java index ca863da0d..fa267d8c0 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/IpaComparator.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/IpaComparator.java @@ -233,7 +233,11 @@ public void finishChecks() throws IOException { Utilities.createDirectory(Utilities.path(dstDir, "ipa-comparison-v"+vi.version)); ComparisonRenderer cr = new ComparisonRenderer(vi.context, context, Utilities.path(dstDir, "ipa-comparison-v"+vi.version), session); cr.getTemplates().put("CodeSystem", new String(context.getBinaryForKey("template-comparison-CodeSystem.html"))); + cr.getTemplates().put("CodeSystem-Union", new String(context.getBinaryForKey("template-comparison-CodeSystem-Union.html"))); + cr.getTemplates().put("CodeSystem-Intersection", new String(context.getBinaryForKey("template-comparison-CodeSystem-Intersection.html"))); cr.getTemplates().put("ValueSet", new String(context.getBinaryForKey("template-comparison-ValueSet.html"))); + cr.getTemplates().put("ValueSet-Union", new String(context.getBinaryForKey("template-comparison-ValueSet-Union.html"))); + cr.getTemplates().put("ValueSet-Intersection", new String(context.getBinaryForKey("template-comparison-ValueSet-Intersection.html"))); cr.getTemplates().put("Profile", new String(context.getBinaryForKey("template-comparison-Profile.html"))); cr.getTemplates().put("Profile-Union", new String(context.getBinaryForKey("template-comparison-Profile-Union.html"))); cr.getTemplates().put("Profile-Intersection", new String(context.getBinaryForKey("template-comparison-Profile-Intersection.html"))); diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/IpsComparator.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/IpsComparator.java index 81747475c..922669004 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/IpsComparator.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/IpsComparator.java @@ -233,7 +233,11 @@ public void finishChecks() throws IOException { Utilities.createDirectory(Utilities.path(dstDir, "ips-comparison-v"+vi.version)); ComparisonRenderer cr = new ComparisonRenderer(vi.context, context, Utilities.path(dstDir, "ips-comparison-v"+vi.version), session); cr.getTemplates().put("CodeSystem", new String(context.getBinaryForKey("template-comparison-CodeSystem.html"))); + cr.getTemplates().put("CodeSystem-Union", new String(context.getBinaryForKey("template-comparison-CodeSystem-Union.html"))); + cr.getTemplates().put("CodeSystem-Intersection", new String(context.getBinaryForKey("template-comparison-CodeSystem-Intersection.html"))); cr.getTemplates().put("ValueSet", new String(context.getBinaryForKey("template-comparison-ValueSet.html"))); + cr.getTemplates().put("ValueSet-Union", new String(context.getBinaryForKey("template-comparison-ValueSet-Union.html"))); + cr.getTemplates().put("ValueSet-Intersection", new String(context.getBinaryForKey("template-comparison-ValueSet-Intersection.html"))); cr.getTemplates().put("Profile", new String(context.getBinaryForKey("template-comparison-Profile.html"))); cr.getTemplates().put("Profile-Union", new String(context.getBinaryForKey("template-comparison-Profile-Union.html"))); cr.getTemplates().put("Profile-Intersection", new String(context.getBinaryForKey("template-comparison-Profile-Intersection.html"))); diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/PreviousVersionComparator.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/PreviousVersionComparator.java index 5285687f0..2864df610 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/PreviousVersionComparator.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/comparators/PreviousVersionComparator.java @@ -263,7 +263,11 @@ public void finishChecks() throws IOException { Utilities.createDirectory(Utilities.path(dstDir, "comparison-v"+vi.version)); ComparisonRenderer cr = new ComparisonRenderer(vi.context, context, Utilities.path(dstDir, "comparison-v"+vi.version), session); cr.getTemplates().put("CodeSystem", new String(context.getBinaryForKey("template-comparison-CodeSystem.html"))); + cr.getTemplates().put("CodeSystem-Union", new String(context.getBinaryForKey("template-comparison-CodeSystem-Union.html"))); + cr.getTemplates().put("CodeSystem-Intersection", new String(context.getBinaryForKey("template-comparison-CodeSystem-Intersection.html"))); cr.getTemplates().put("ValueSet", new String(context.getBinaryForKey("template-comparison-ValueSet.html"))); + cr.getTemplates().put("ValueSet-Union", new String(context.getBinaryForKey("template-comparison-ValueSet-Union.html"))); + cr.getTemplates().put("ValueSet-Intersection", new String(context.getBinaryForKey("template-comparison-ValueSet-Intersection.html"))); cr.getTemplates().put("Profile", new String(context.getBinaryForKey("template-comparison-Profile.html"))); cr.getTemplates().put("Profile-Union", new String(context.getBinaryForKey("template-comparison-Profile-Union.html"))); cr.getTemplates().put("Profile-Intersection", new String(context.getBinaryForKey("template-comparison-Profile-Intersection.html"))); diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/realm/USRealmBusinessRules.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/realm/USRealmBusinessRules.java index 34b48a45b..415ac5888 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/realm/USRealmBusinessRules.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/realm/USRealmBusinessRules.java @@ -240,6 +240,8 @@ public void finishChecks() throws DefinitionException, FHIRFormatError, IOExcept cr.getTemplates().put("Profile", new String(context.getBinaryForKey("template-comparison-Profile.html"))); cr.getTemplates().put("Profile-Union", new String(context.getBinaryForKey("template-comparison-Profile-Union.html"))); cr.getTemplates().put("Profile-Intersection", new String(context.getBinaryForKey("template-comparison-Profile-Intersection.html"))); + cr.getTemplates().put("CodeSystem-Union", new String(context.getBinaryForKey("template-comparison-CodeSystem-Union.html"))); + cr.getTemplates().put("CodeSystem-Intersection", new String(context.getBinaryForKey("template-comparison-CodeSystem-Intersection.html"))); cr.getTemplates().put("CapabilityStatement", new String(context.getBinaryForKey("template-comparison-CapabilityStatement.html"))); cr.getTemplates().put("Index", new String(context.getBinaryForKey("template-comparison-index.html"))); cr.setPreamble(renderProblems()); diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/utils/TemplateReleaser.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/utils/TemplateReleaser.java index 680b1c428..bb5e27e94 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/utils/TemplateReleaser.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/publisher/utils/TemplateReleaser.java @@ -233,9 +233,9 @@ private void buildIndexPage(Map currentVersions, String path) th for (String id : Utilities.sorted(currentVersions.keySet())) { tr = tbl.tr(); PackageList pl = new PackageList(JsonParser.parseObject(new File(Utilities.path(path, id, "package-list.json")))); - tr.td().ah("http://fhir.org/templates/"+id).tx(pl.pid()); + tr.td().ah(id).tx(pl.pid()); tr.td().tx(pl.title()); - tr.td().ah("http://fhir.org/templates/"+id+"/"+pl.current().version()+"/package.tgz").tx(pl.current().version()); + tr.td().ah(id+"/"+pl.current().version()+"/package.tgz").tx(pl.current().version()); tr.td().tx(pl.current().date()); } String s = INDEX_TEMPLATE.replace("{{index}}", new XhtmlComposer(false, false).compose(tbl)); diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/CodeSystemRenderer.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/CodeSystemRenderer.java index dd217ad99..aa61f99ab 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/CodeSystemRenderer.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/CodeSystemRenderer.java @@ -185,6 +185,8 @@ protected void changeSummaryDetails(StringBuilder b) { b.append("
  • One or more text definitions/displays have changed
  • \r\n"); } + } else if (comp == null) { + b.append("
  • New Content
  • \r\n"); } else { b.append("
  • No changes
  • \r\n"); } diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/StructureDefinitionRenderer.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/StructureDefinitionRenderer.java index 27c794f40..a3b2813ea 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/StructureDefinitionRenderer.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/StructureDefinitionRenderer.java @@ -2534,6 +2534,8 @@ protected void changeSummaryDetails(StringBuilder b) { } else if (comp.getChangedDefinitions() == ChangeAnalysisState.Changed) { b.append("
  • One or more text definitions, invariants or bindings have changed
  • \r\n"); } + } else if (comp == null) { + b.append("
  • New Content
  • \r\n"); } else { b.append("
  • No changes
  • \r\n"); } diff --git a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/ValueSetRenderer.java b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/ValueSetRenderer.java index b705b8059..a8de73714 100644 --- a/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/ValueSetRenderer.java +++ b/org.hl7.fhir.publisher.core/src/main/java/org/hl7/fhir/igtools/renderers/ValueSetRenderer.java @@ -276,6 +276,8 @@ protected void changeSummaryDetails(StringBuilder b) { } else { b.append("
  • No changes
  • \r\n"); } + } else { + b.append("
  • New Content
  • \r\n"); } } }