wip
This commit is contained in:
parent
7affad01fc
commit
8c3e03399e
|
@ -24,6 +24,8 @@ package org.hl7.fhir.r5.elementmodel;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
|
@ -34,22 +36,34 @@ import org.hl7.fhir.r5.model.StructureDefinition;
|
|||
|
||||
public class Manager {
|
||||
|
||||
public enum FhirFormat { XML, JSON, TURTLE, TEXT, VBAR;
|
||||
//TODO use EnumMap
|
||||
public enum FhirFormat {
|
||||
XML("xml"),
|
||||
JSON("json"),
|
||||
TURTLE("ttl"),
|
||||
TEXT("txt"),
|
||||
VBAR("hl7");
|
||||
|
||||
final String extension;
|
||||
|
||||
FhirFormat(String extension) {
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
switch (this) {
|
||||
case JSON:
|
||||
return "json";
|
||||
case TURTLE:
|
||||
return "ttl";
|
||||
case XML:
|
||||
return "xml";
|
||||
case TEXT:
|
||||
return "txt";
|
||||
case VBAR:
|
||||
return "hl7";
|
||||
return this.extension;
|
||||
}
|
||||
|
||||
private static final Map<String, FhirFormat> lookup = new HashMap<>();
|
||||
|
||||
static {
|
||||
for(FhirFormat ff : FhirFormat.values()) {
|
||||
lookup.put(ff.getExtension(), ff);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static FhirFormat get(String extension) {
|
||||
return lookup.get(extension);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ package org.hl7.fhir.utilities.validation;
|
|||
*/
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
<artifactId>org.hl7.fhir.validation</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<properties>
|
||||
<micronaut.version>1.3.4</micronaut.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- HAPI Dependencies -->
|
||||
|
@ -99,12 +103,26 @@
|
|||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.hl7.fhir.testcases</groupId>
|
||||
<artifactId>fhir-test-cases</artifactId>
|
||||
<version>${validator_test_case_version}</version>
|
||||
<scope>test</scope>
|
||||
<groupId>io.javalin</groupId>
|
||||
<artifactId>javalin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.28</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.10.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
<version>3.0.9.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
|
|
@ -1070,6 +1070,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return isBundle;
|
||||
}
|
||||
|
||||
public OperationOutcome validate(byte[] source, FhirFormat cntType, List<String> profiles) throws Exception {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
InstanceValidator validator = getValidator();
|
||||
validator.validate(null, messages, new ByteArrayInputStream(source), cntType, asSdList(profiles));
|
||||
return messagesToOutcome(messages);
|
||||
}
|
||||
|
||||
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles) throws Exception {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
if (doNative) {
|
||||
|
|
|
@ -49,12 +49,17 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
import org.hl7.fhir.r5.model.ImplementationGuide;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.validation.cli.*;
|
||||
import org.hl7.fhir.validation.cli.ValidatorGui;
|
||||
import org.hl7.fhir.validation.cli.services.ComparisonService;
|
||||
import org.hl7.fhir.validation.cli.services.ValidationService;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.hl7.fhir.validation.cli.utils.*;
|
||||
|
||||
/**
|
||||
* A executable class that will validate one or more FHIR resources against
|
||||
|
@ -75,6 +80,8 @@ public class Validator {
|
|||
VALIDATION, TRANSFORM, NARRATIVE, SNAPSHOT, SCAN, CONVERT, FHIRPATH, VERSION
|
||||
}
|
||||
|
||||
private static CliContext cliContext;
|
||||
|
||||
private static String getNamedParam(String[] args, String param) {
|
||||
boolean found = false;
|
||||
for (String a : args) {
|
||||
|
@ -91,7 +98,29 @@ public class Validator {
|
|||
return Long.toString(maxMemory / (1024 * 1024));
|
||||
}
|
||||
|
||||
private static CliContext getCliContext() {
|
||||
if (cliContext == null) {
|
||||
cliContext = new CliContext();
|
||||
}
|
||||
return cliContext;
|
||||
}
|
||||
|
||||
private static void goToWebPage(String url) {
|
||||
try {
|
||||
|
||||
URI uri= new URI(url);
|
||||
|
||||
java.awt.Desktop.getDesktop().browse(uri);
|
||||
System.out.println("Web page opened in browser");
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
System.out.println("FHIR Validation tool " + VersionUtil.getVersionString());
|
||||
System.out.println("Detected Java version: " + System.getProperty("java.version") + " from " + System.getProperty("java.home") + " on " + System.getProperty("os.arch") + " (" + System.getProperty("sun.arch.data.model") + "bit). " + toMB(Runtime.getRuntime().maxMemory()) + "MB available");
|
||||
String proxy = getNamedParam(args, Params.PROXY);
|
||||
|
@ -101,7 +130,13 @@ public class Validator {
|
|||
System.setProperty("http.proxyPort", p[1]);
|
||||
}
|
||||
|
||||
if (Params.hasParam(args, Params.TEST)) {
|
||||
if (Params.hasParam(args, Params.GUI)) {
|
||||
cliContext = Params.loadCliContext(args);
|
||||
String v = Common.getVersion(args);
|
||||
String definitions = VersionUtilities.packageForVersion(v) + "#" + v;
|
||||
ValidationEngine validationEngine = Common.getValidationEngine(v, definitions, cliContext.getTxLog());
|
||||
ValidatorGui.start(cliContext, validationEngine);
|
||||
}else if (Params.hasParam(args, Params.TEST)) {
|
||||
Common.runValidationEngineTests();
|
||||
} else if (args.length == 0 || Params.hasParam(args, Params.HELP) || Params.hasParam(args, "?") || Params.hasParam(args, "-?") || Params.hasParam(args, "/?")) {
|
||||
Display.displayHelpDetails();
|
||||
|
@ -115,30 +150,32 @@ public class Validator {
|
|||
else {
|
||||
// first, prepare the context
|
||||
String txLog = Params.getTerminologyServerLog(args);
|
||||
ValidationEngine validator = Common.getValidationEngine(args, txLog);
|
||||
String v = Common.getVersion(args);
|
||||
String definitions = VersionUtilities.packageForVersion(v) + "#" + v;
|
||||
ValidationEngine validator = Common.getValidationEngine(v, definitions, txLog);
|
||||
Params.checkIGFileReferences(args);
|
||||
Comparison.doLeftRightComparison(args, dest, validator);
|
||||
ComparisonService.doLeftRightComparison(args, dest, validator);
|
||||
}
|
||||
} else {
|
||||
Display.printCliArgumentsAndInfo(args);
|
||||
CliContext cliContext = Params.loadCliContext(args);
|
||||
cliContext = Params.loadCliContext(args);
|
||||
|
||||
// Comment this out because definitions filename doesn't necessarily contain version (and many not even be 14 characters long). Version gets spit out a couple of lines later after we've loaded the context
|
||||
String definitions = VersionUtilities.packageForVersion(cliContext.getSv()) + "#" + VersionUtilities.getCurrentVersion(cliContext.getSv());
|
||||
ValidationEngine validator = ValidationUtils.getValidator(cliContext, definitions);
|
||||
|
||||
ValidationEngine validator = ValidationService.getValidator(cliContext, definitions);
|
||||
if (cliContext.getMode() == EngineMode.VERSION) {
|
||||
ValidationUtils.transformVersion(cliContext, validator);
|
||||
|
||||
ValidationService.transformVersion(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.TRANSFORM) {
|
||||
ValidationUtils.transform(cliContext, validator);
|
||||
ValidationService.transform(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.NARRATIVE) {
|
||||
ValidationUtils.generateNarrative(cliContext, validator);
|
||||
ValidationService.generateNarrative(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.SNAPSHOT) {
|
||||
ValidationUtils.generateSnapshot(cliContext, validator);
|
||||
ValidationService.generateSnapshot(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.CONVERT) {
|
||||
ValidationUtils.convertSources(cliContext, validator);
|
||||
ValidationService.convertSources(cliContext, validator);
|
||||
} else if (cliContext.getMode() == EngineMode.FHIRPATH) {
|
||||
ValidationUtils.evaluateFhirpath(cliContext, validator);
|
||||
ValidationService.evaluateFhirpath(cliContext, validator);
|
||||
} else {
|
||||
if (definitions == null) {
|
||||
throw new Exception("Must provide a defn when doing validation");
|
||||
|
@ -150,9 +187,9 @@ public class Validator {
|
|||
}
|
||||
}
|
||||
if (cliContext.getMode() == EngineMode.SCAN) {
|
||||
ValidationUtils.validateScan(cliContext, validator);
|
||||
ValidationService.validateScan(cliContext, validator);
|
||||
} else {
|
||||
ValidationUtils.validateSources(cliContext, validator);
|
||||
ValidationService.validateSources(cliContext, validator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.javalin.Javalin;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.cli.controller.CliContextController;
|
||||
import org.hl7.fhir.validation.cli.controller.ValidationController;
|
||||
import org.hl7.fhir.validation.cli.controller.UIController;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
|
||||
public class RestEndpoints {
|
||||
|
||||
public UIController myUIController;
|
||||
public CliContextController myCliContextController;
|
||||
public ValidationController myValidationController;
|
||||
|
||||
public void initRestEndpoints(Javalin app, CliContext cliContext, ValidationEngine validationEngine) {
|
||||
|
||||
myUIController = new UIController();
|
||||
myCliContextController = new CliContextController(cliContext);
|
||||
myValidationController = new ValidationController(validationEngine);
|
||||
|
||||
app.get("/home", myUIController.renderLandingPage);
|
||||
|
||||
app.get("/context", myCliContextController.getCurrentCliContext);
|
||||
app.post("/context", myCliContextController.setCurrentCliContext);
|
||||
|
||||
app.post("/validate", myValidationController.handleValidationRequest);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
|
||||
import io.javalin.Javalin;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.hl7.fhir.validation.cli.utils.Common;
|
||||
|
||||
public class ValidatorGui {
|
||||
|
||||
private static final String WEB_APP_FILE_LOCATION = "/public";
|
||||
private static Javalin app;
|
||||
|
||||
/**
|
||||
* N.B. this entry point, is only for testing. Please start from command line using the argument {@code -gui} for
|
||||
* actual use.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
CliContext cliContext = new CliContext();
|
||||
String v = Common.getVersion(args);
|
||||
String definitions = VersionUtilities.packageForVersion(v) + "#" + v;
|
||||
ValidationEngine validationEngine = Common.getValidationEngine(v, definitions, cliContext.getTxLog());
|
||||
start(new CliContext(), validationEngine);
|
||||
}
|
||||
|
||||
public static void start(CliContext currentContext, ValidationEngine validationEngine) {
|
||||
app = Javalin.create();
|
||||
new RestEndpoints().initRestEndpoints(app, new CliContext(), validationEngine);
|
||||
app.config.addStaticFiles(WEB_APP_FILE_LOCATION);
|
||||
app.start(8080);
|
||||
}
|
||||
|
||||
public static void stop() {
|
||||
app.stop();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package org.hl7.fhir.validation.cli.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.javalin.http.Handler;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
|
||||
public class CliContextController {
|
||||
|
||||
private CliContext myCliContext;
|
||||
|
||||
public CliContextController(CliContext cliContext) {
|
||||
this.myCliContext = cliContext;
|
||||
}
|
||||
|
||||
public Handler getCurrentCliContext = ctx -> {
|
||||
ObjectMapper Obj = new ObjectMapper();
|
||||
String jsonStr = Obj.writeValueAsString(myCliContext);
|
||||
ctx.result(jsonStr);
|
||||
};
|
||||
|
||||
public Handler setCurrentCliContext = ctx -> {
|
||||
myCliContext = ctx.bodyAsClass(CliContext.class);
|
||||
ctx.status(HttpStatus.SC_CREATED);
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package org.hl7.fhir.validation.cli.controller;
|
||||
|
||||
import io.javalin.http.Handler;
|
||||
|
||||
public class UIController {
|
||||
|
||||
public UIController() {}
|
||||
|
||||
public Handler renderLandingPage = ctx -> {
|
||||
ctx.render("/public/test.html");
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package org.hl7.fhir.validation.cli.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.javalin.http.Handler;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.cli.model.ValidationRequest;
|
||||
import org.hl7.fhir.validation.cli.model.ValidationResponse;
|
||||
import org.hl7.fhir.validation.cli.services.ValidationService;
|
||||
|
||||
public class ValidationController {
|
||||
|
||||
private ValidationEngine myValidationEngine;
|
||||
|
||||
public ValidationController(ValidationEngine validationEngine) {
|
||||
this.myValidationEngine = validationEngine;
|
||||
}
|
||||
|
||||
public Handler handleValidationRequest = ctx -> {
|
||||
ValidationRequest request = ctx.bodyAsClass(ValidationRequest.class);
|
||||
ValidationResponse response = ValidationService.validateSources(request, myValidationEngine);
|
||||
|
||||
// File new temp file
|
||||
// DeleteOnShutdown
|
||||
|
||||
ObjectMapper Obj = new ObjectMapper();
|
||||
String jsonStr = Obj.writeValueAsString(response);
|
||||
|
||||
ctx.status(200).json(jsonStr);
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"outcomes": [
|
||||
{
|
||||
"fileInfo": {
|
||||
"fileName": "account-example.canonical.json",
|
||||
"fileContent": "{\"id\":\"example\",\"resourceType\":\"Account\",\"text\":{\"div\":\"<div>[Put rendering here]</div>\",\"status\":\"generated\"}}",
|
||||
"fileType": "JSON"
|
||||
},
|
||||
"issues": [
|
||||
{
|
||||
"severity": "Error",
|
||||
"details": "Wrong namespace on the XHTML (\"null\", should be \"http://www.w3.org/1999/xhtml\")"
|
||||
},
|
||||
{
|
||||
"severity": "Error",
|
||||
"details": "Profile http://hl7.org/fhir/StructureDefinition/Account, Element 'Account.status': minimum required = 1, but only found 0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"fileInfo": {
|
||||
"fileName": "account-example(example).xml",
|
||||
"fileContent": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Account xmlns=\"http://hl7.org/fhir\">\n\t<id value=\"example\"/>\n\t<meta>\n <security>\n <system value=\"http://terminology.hl7.org/CodeSystem/v3-ActReason\"/>\n <code value=\"HTEST\"/>\n <display value=\"test health data\"/>\n </security>\n </meta>\n <text>\n\t\t<status value=\"generated\"/>\n\t\t<div xmlns=\"http://www.w3.org/1999/xhtml\">HACC Funded Billing for Peter James Chalmers</div>\n\t</text>\n\t<identifier>\n\t\t<system value=\"urn:oid:0.1.2.3.4.5.6.7\"/>\n\t\t<value value=\"654321\"/>\n\t</identifier>\n\t<status value=\"active\"/>\n\t<type>\n\t\t<coding>\n\t\t\t<system value=\"http://terminology.hl7.org/CodeSystem/v3-ActCode\"/>\n\t\t\t<code value=\"PBILLACCT\"/>\n\t\t\t<display value=\"patient billing account\"/>\n\t\t</coding>\n\t\t<text value=\"patient\"/>\n\t</type>\n\t<name value=\"HACC Funded Billing for Peter James Chalmers\"/>\n\t<subject>\n\t\t<reference value=\"Patient/example\"/>\n\t\t<display value=\"Peter James Chalmers\"/>\n\t</subject>\n\t<servicePeriod>\n\t\t<start value=\"2016-01-01\"/>\n\t\t<end value=\"2016-06-30\"/>\n\t</servicePeriod>\n\t<coverage>\n\t\t<coverage>\n\t\t\t<reference value=\"Coverage/7546D\"/>\n\t\t</coverage>\n\t\t<priority value=\"1\"/>\n\t</coverage>\n\t<owner>\n\t\t<reference value=\"Organization/hl7\"/>\n\t</owner>\n\t<description value=\"Hospital charges\"/>\n</Account>",
|
||||
"fileType": "XML"
|
||||
},
|
||||
"issues": []
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.hl7.fhir.validation.Validator;
|
||||
import org.hl7.fhir.validation.cli.utils.SnomedVersion;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -9,44 +11,78 @@ import java.util.*;
|
|||
*/
|
||||
public class CliContext {
|
||||
|
||||
private String map = null;
|
||||
private List<String> igs = new ArrayList<String>();
|
||||
private List<String> questionnaires = new ArrayList<String>();
|
||||
private String txServer = "http://tx.fhir.org";
|
||||
@JsonProperty("doNative")
|
||||
private boolean doNative = false;
|
||||
@JsonProperty("anyExtensionsAllowed")
|
||||
private boolean anyExtensionsAllowed = true;
|
||||
@JsonProperty("hintAboutNonMustSupport")
|
||||
private boolean hintAboutNonMustSupport = false;
|
||||
@JsonProperty("recursive")
|
||||
private boolean recursive = false;
|
||||
private Locale locale = null;
|
||||
private List<String> profiles = new ArrayList<String>();
|
||||
private Validator.EngineMode mode = Validator.EngineMode.VALIDATION;
|
||||
private String output = null;
|
||||
private Boolean canDoNative = null;
|
||||
private List<String> sources = new ArrayList<String>();
|
||||
private Map<String, String> locations = new HashMap<String, String>();
|
||||
private String sv = "current";
|
||||
private String txLog = null;
|
||||
private String mapLog = null;
|
||||
private String lang = null;
|
||||
private String fhirpath = null;
|
||||
private String snomedCT = SnomedVersion.INTL.getCode();
|
||||
private String targetVer = null;
|
||||
@JsonProperty("doDebug")
|
||||
private boolean doDebug = false;
|
||||
@JsonProperty("assumeValidRestReferences")
|
||||
private boolean assumeValidRestReferences = false;
|
||||
@JsonProperty("canDoNative")
|
||||
private boolean canDoNative = false;
|
||||
|
||||
@JsonProperty("map")
|
||||
private String map = null;
|
||||
@JsonProperty("output")
|
||||
private String output = null;
|
||||
@JsonProperty("txServer")
|
||||
private String txServer = "http://tx.fhir.org";
|
||||
@JsonProperty("sv")
|
||||
private String sv = "current";
|
||||
@JsonProperty("txLog")
|
||||
private String txLog = null;
|
||||
@JsonProperty("mapLog")
|
||||
private String mapLog = null;
|
||||
@JsonProperty("lang")
|
||||
private String lang = null;
|
||||
@JsonProperty("fhirpath")
|
||||
private String fhirpath = null;
|
||||
@JsonProperty("snomedCT")
|
||||
private String snomedCT = SnomedVersion.INTL.getCode();
|
||||
@JsonProperty("targetVer")
|
||||
private String targetVer = null;
|
||||
|
||||
@JsonProperty("igs")
|
||||
private List<String> igs = new ArrayList<String>();
|
||||
@JsonProperty("questionnaires")
|
||||
private List<String> questionnaires = new ArrayList<String>();
|
||||
@JsonProperty("profiles")
|
||||
private List<String> profiles = new ArrayList<String>();
|
||||
@JsonProperty("sources")
|
||||
private List<String> sources = new ArrayList<String>();
|
||||
|
||||
@JsonProperty("mode")
|
||||
private Validator.EngineMode mode = Validator.EngineMode.VALIDATION;
|
||||
|
||||
@JsonProperty("locale")
|
||||
private Locale locale = null;
|
||||
|
||||
@JsonProperty("locations")
|
||||
private Map<String, String> locations = new HashMap<String, String>();
|
||||
|
||||
|
||||
@JsonProperty("map")
|
||||
public String getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
@JsonProperty("map")
|
||||
public CliContext setMap(String map) {
|
||||
this.map = map;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("igs")
|
||||
public List<String> getIgs() {
|
||||
return igs;
|
||||
}
|
||||
|
||||
@JsonProperty("igs")
|
||||
public CliContext setIgs(List<String> igs) {
|
||||
this.igs = igs;
|
||||
return this;
|
||||
|
@ -60,10 +96,12 @@ public class CliContext {
|
|||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("questionnaires")
|
||||
public List<String> getQuestionnaires() {
|
||||
return questionnaires;
|
||||
}
|
||||
|
||||
@JsonProperty("questionnaires")
|
||||
public CliContext setQuestionnaires(List<String> questionnaires) {
|
||||
this.questionnaires = questionnaires;
|
||||
return this;
|
||||
|
@ -77,64 +115,87 @@ public class CliContext {
|
|||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("txServer")
|
||||
public String getTxServer() {
|
||||
return txServer;
|
||||
}
|
||||
|
||||
@JsonProperty("txServer")
|
||||
public CliContext setTxServer(String txServer) {
|
||||
this.txServer = txServer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("doNative")
|
||||
public boolean isDoNative() {
|
||||
return doNative;
|
||||
}
|
||||
|
||||
@JsonProperty("doNative")
|
||||
public CliContext setDoNative(boolean doNative) {
|
||||
this.doNative = doNative;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("anyExtensionsAllowed")
|
||||
public boolean isAnyExtensionsAllowed() {
|
||||
return anyExtensionsAllowed;
|
||||
}
|
||||
|
||||
@JsonProperty("anyExtensionsAllowed")
|
||||
public CliContext setAnyExtensionsAllowed(boolean anyExtensionsAllowed) {
|
||||
this.anyExtensionsAllowed = anyExtensionsAllowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("hintAboutNonMustSupport")
|
||||
public boolean isHintAboutNonMustSupport() {
|
||||
return hintAboutNonMustSupport;
|
||||
}
|
||||
|
||||
@JsonProperty("hintAboutNonMustSupport")
|
||||
public CliContext setHintAboutNonMustSupport(boolean hintAboutNonMustSupport) {
|
||||
this.hintAboutNonMustSupport = hintAboutNonMustSupport;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("recursive")
|
||||
public boolean isRecursive() {
|
||||
return recursive;
|
||||
}
|
||||
|
||||
@JsonProperty("recursive")
|
||||
public CliContext setRecursive(boolean recursive) {
|
||||
this.recursive = recursive;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("locale")
|
||||
public String getLanguageCode() {
|
||||
return this.locale.getDisplayLanguage();
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
@JsonProperty("locale")
|
||||
public CliContext setLocale(String languageString) {
|
||||
this.locale = new Locale(languageString);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CliContext setLocale(Locale locale) {
|
||||
this.locale = locale;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("profiles")
|
||||
public List<String> getProfiles() {
|
||||
return profiles;
|
||||
}
|
||||
|
||||
@JsonProperty("profiles")
|
||||
public CliContext setProfiles(List<String> profiles) {
|
||||
this.profiles = profiles;
|
||||
return this;
|
||||
|
@ -148,37 +209,45 @@ public class CliContext {
|
|||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("mode")
|
||||
public Validator.EngineMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
@JsonProperty("mode")
|
||||
public CliContext setMode(Validator.EngineMode mode) {
|
||||
this.mode = mode;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("output")
|
||||
public String getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
@JsonProperty("output")
|
||||
public CliContext setOutput(String output) {
|
||||
this.output = output;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean getCanDoNative() {
|
||||
@JsonProperty("canDoNative")
|
||||
public boolean getCanDoNative() {
|
||||
return canDoNative;
|
||||
}
|
||||
|
||||
public CliContext setCanDoNative(Boolean canDoNative) {
|
||||
@JsonProperty("canDoNative")
|
||||
public CliContext setCanDoNative(boolean canDoNative) {
|
||||
this.canDoNative = canDoNative;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("sources")
|
||||
public List<String> getSources() {
|
||||
return sources;
|
||||
}
|
||||
|
||||
@JsonProperty("sources")
|
||||
public CliContext setSources(List<String> sources) {
|
||||
this.sources = sources;
|
||||
return this;
|
||||
|
@ -192,10 +261,12 @@ public class CliContext {
|
|||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("locations")
|
||||
public Map<String, String> getLocations() {
|
||||
return locations;
|
||||
}
|
||||
|
||||
@JsonProperty("locations")
|
||||
public CliContext setLocations(Map<String, String> locations) {
|
||||
this.locations = locations;
|
||||
return this;
|
||||
|
@ -206,84 +277,132 @@ public class CliContext {
|
|||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("sv")
|
||||
public String getSv() {
|
||||
return sv;
|
||||
}
|
||||
|
||||
@JsonProperty("sv")
|
||||
public CliContext setSv(String sv) {
|
||||
this.sv = sv;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("txLog")
|
||||
public String getTxLog() {
|
||||
return txLog;
|
||||
}
|
||||
|
||||
@JsonProperty("txLog")
|
||||
public CliContext setTxLog(String txLog) {
|
||||
this.txLog = txLog;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("mapLog")
|
||||
public String getMapLog() {
|
||||
return mapLog;
|
||||
}
|
||||
|
||||
@JsonProperty("mapLog")
|
||||
public CliContext setMapLog(String mapLog) {
|
||||
this.mapLog = mapLog;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("lang")
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
@JsonProperty("lang")
|
||||
public CliContext setLang(String lang) {
|
||||
this.lang = lang;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("fhirpath")
|
||||
public String getFhirpath() {
|
||||
return fhirpath;
|
||||
}
|
||||
|
||||
@JsonProperty("fhirpath")
|
||||
public CliContext setFhirpath(String fhirpath) {
|
||||
this.fhirpath = fhirpath;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("snomedCT")
|
||||
public String getSnomedCT() {
|
||||
return snomedCT;
|
||||
}
|
||||
|
||||
@JsonProperty("snomedCT")
|
||||
public CliContext setSnomedCT(String snomedCT) {
|
||||
this.snomedCT = SnomedVersion.resolveSnomedCTCode(snomedCT);
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("targetVer")
|
||||
public String getTargetVer() {
|
||||
return targetVer;
|
||||
}
|
||||
|
||||
@JsonProperty("targetVer")
|
||||
public CliContext setTargetVer(String targetVer) {
|
||||
this.targetVer = targetVer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("doDebug")
|
||||
public boolean isDoDebug() {
|
||||
return doDebug;
|
||||
}
|
||||
|
||||
@JsonProperty("doDebug")
|
||||
public CliContext setDoDebug(boolean doDebug) {
|
||||
this.doDebug = doDebug;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("assumeValidRestReferences")
|
||||
public boolean isAssumeValidRestReferences() {
|
||||
return assumeValidRestReferences;
|
||||
}
|
||||
|
||||
@JsonProperty("assumeValidRestReferences")
|
||||
public CliContext setAssumeValidRestReferences(boolean assumeValidRestReferences) {
|
||||
this.assumeValidRestReferences = assumeValidRestReferences;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CliContext{" +
|
||||
"map='" + map + '\'' +
|
||||
", igs=" + igs +
|
||||
", questionnaires=" + questionnaires +
|
||||
", txServer='" + txServer + '\'' +
|
||||
", doNative=" + doNative +
|
||||
", anyExtensionsAllowed=" + anyExtensionsAllowed +
|
||||
", hintAboutNonMustSupport=" + hintAboutNonMustSupport +
|
||||
", recursive=" + recursive +
|
||||
", locale=" + locale +
|
||||
", profiles=" + profiles +
|
||||
", mode=" + mode +
|
||||
", output='" + output + '\'' +
|
||||
", canDoNative=" + canDoNative +
|
||||
", sources=" + sources +
|
||||
", locations=" + locations +
|
||||
", sv='" + sv + '\'' +
|
||||
", txLog='" + txLog + '\'' +
|
||||
", mapLog='" + mapLog + '\'' +
|
||||
", lang='" + lang + '\'' +
|
||||
", fhirpath='" + fhirpath + '\'' +
|
||||
", snomedCT='" + snomedCT + '\'' +
|
||||
", targetVer='" + targetVer + '\'' +
|
||||
", doDebug=" + doDebug +
|
||||
", assumeValidRestReferences=" + assumeValidRestReferences +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
/**
|
||||
* A POJO for storing the flags/values for the CLI validator.
|
||||
*/
|
||||
public class CliContextTest {
|
||||
|
||||
private boolean doNative = false;
|
||||
private boolean anyExtensionsAllowed = true;
|
||||
private boolean hintAboutNonMustSupport = false;
|
||||
private boolean recursive = false;
|
||||
private boolean doDebug = false;
|
||||
private boolean assumeValidRestReferences = false;
|
||||
|
||||
public boolean isDoNative() {
|
||||
return doNative;
|
||||
}
|
||||
|
||||
public CliContextTest setDoNative(boolean doNative) {
|
||||
this.doNative = doNative;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isAnyExtensionsAllowed() {
|
||||
return anyExtensionsAllowed;
|
||||
}
|
||||
|
||||
public CliContextTest setAnyExtensionsAllowed(boolean anyExtensionsAllowed) {
|
||||
this.anyExtensionsAllowed = anyExtensionsAllowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isHintAboutNonMustSupport() {
|
||||
return hintAboutNonMustSupport;
|
||||
}
|
||||
|
||||
public CliContextTest setHintAboutNonMustSupport(boolean hintAboutNonMustSupport) {
|
||||
this.hintAboutNonMustSupport = hintAboutNonMustSupport;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isRecursive() {
|
||||
return recursive;
|
||||
}
|
||||
|
||||
public CliContextTest setRecursive(boolean recursive) {
|
||||
this.recursive = recursive;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isDoDebug() {
|
||||
return doDebug;
|
||||
}
|
||||
|
||||
public CliContextTest setDoDebug(boolean doDebug) {
|
||||
this.doDebug = doDebug;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isAssumeValidRestReferences() {
|
||||
return assumeValidRestReferences;
|
||||
}
|
||||
|
||||
public CliContextTest setAssumeValidRestReferences(boolean assumeValidRestReferences) {
|
||||
this.assumeValidRestReferences = assumeValidRestReferences;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CliContext{" +
|
||||
", doNative=" + doNative +
|
||||
", anyExtensionsAllowed=" + anyExtensionsAllowed +
|
||||
", hintAboutNonMustSupport=" + hintAboutNonMustSupport +
|
||||
", recursive=" + recursive +
|
||||
", doDebug=" + doDebug +
|
||||
", assumeValidRestReferences=" + assumeValidRestReferences +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.hl7.fhir.r5.elementmodel.Manager;
|
||||
|
||||
public class FileInfo {
|
||||
|
||||
@JsonProperty("fileName")
|
||||
private String fileName;
|
||||
|
||||
@JsonProperty("fileContent")
|
||||
private String fileContent;
|
||||
|
||||
@JsonProperty("fileType")
|
||||
private String fileType;
|
||||
|
||||
@JsonProperty("fileName")
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@JsonProperty("fileName")
|
||||
public FileInfo setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("fileContent")
|
||||
public String getFileContent() {
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
@JsonProperty("fileContent")
|
||||
public FileInfo setFileContent(String fileContent) {
|
||||
this.fileContent = fileContent;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("fileType")
|
||||
public Manager.FhirFormat getFileType() {
|
||||
return Manager.FhirFormat.get(fileType);
|
||||
}
|
||||
|
||||
@JsonProperty("fileType")
|
||||
public FileInfo setFileType(String fileType) {
|
||||
this.fileType = fileType;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class ValidationIssue {
|
||||
@JsonProperty("severity")
|
||||
private String severity;
|
||||
@JsonProperty("details")
|
||||
private String details;
|
||||
|
||||
@JsonProperty("severity")
|
||||
public String getSeverity() {
|
||||
return severity;
|
||||
}
|
||||
|
||||
@JsonProperty("severity")
|
||||
public ValidationIssue setSeverity(String severity) {
|
||||
this.severity = severity;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("details")
|
||||
public String getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
@JsonProperty("details")
|
||||
public ValidationIssue setDetails(String details) {
|
||||
this.details = details;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ValidationOutcome {
|
||||
|
||||
@JsonProperty("fileInfo")
|
||||
private FileInfo fileInfo;
|
||||
@JsonProperty("issues")
|
||||
private List<ValidationIssue> issues = new ArrayList<>();
|
||||
|
||||
@JsonProperty("fileInfo")
|
||||
public FileInfo getFileInfo() {
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
@JsonProperty("fileInfo")
|
||||
public ValidationOutcome setFileInfo(FileInfo fileInfo) {
|
||||
this.fileInfo = fileInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("issues")
|
||||
public List<ValidationIssue> getIssues() {
|
||||
return issues;
|
||||
}
|
||||
|
||||
@JsonProperty("issues")
|
||||
public ValidationOutcome setIssues(List<ValidationIssue> issues) {
|
||||
this.issues = issues;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValidationOutcome addIssue(OperationOutcome.OperationOutcomeIssueComponent outcome) {
|
||||
String text = outcome.getDetails().getText();
|
||||
text.replace("\'", "\"");
|
||||
issues.add(new ValidationIssue()
|
||||
.setSeverity(outcome.getSeverity().getDisplay())
|
||||
.setDetails(outcome.getDetails().getText()));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ValidationRequest {
|
||||
|
||||
@JsonProperty("cliContext")
|
||||
private CliContext cliContext;
|
||||
|
||||
@JsonProperty("filesToValidate")
|
||||
private List<FileInfo> filesToValidate = new ArrayList<>();
|
||||
|
||||
@JsonProperty("cliContext")
|
||||
public CliContext getCliContext() {
|
||||
return cliContext;
|
||||
}
|
||||
|
||||
@JsonProperty("cliContext")
|
||||
public ValidationRequest setCliContext(CliContext cliContext) {
|
||||
this.cliContext = cliContext;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonProperty("filesToValidate")
|
||||
public List<FileInfo> getFilesToValidate() {
|
||||
return filesToValidate;
|
||||
}
|
||||
|
||||
@JsonProperty("filesToValidate")
|
||||
public ValidationRequest setFilesToValidate(List<FileInfo> filesToValidate) {
|
||||
this.filesToValidate = filesToValidate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String listSourceFiles() {
|
||||
List<String> fileNames = new ArrayList<>();
|
||||
for (FileInfo fp : filesToValidate) {
|
||||
fileNames.add(fp.getFileName());
|
||||
}
|
||||
return String.join(", ", fileNames);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ValidationResponse {
|
||||
|
||||
@JsonProperty("outcomes")
|
||||
public List<ValidationOutcome> outcomes = new ArrayList<>();
|
||||
|
||||
@JsonProperty("outcomes")
|
||||
public List<ValidationOutcome> getOutcomes() {
|
||||
return outcomes;
|
||||
}
|
||||
|
||||
@JsonProperty("outcomes")
|
||||
public ValidationResponse setOutcomes(List<ValidationOutcome> outcomes) {
|
||||
this.outcomes = outcomes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValidationResponse addOutcome(ValidationOutcome outcome) {
|
||||
if (outcomes == null) {
|
||||
outcomes = new ArrayList<>();
|
||||
}
|
||||
outcomes.add(outcome);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
package org.hl7.fhir.validation.cli.services;
|
||||
|
||||
import org.hl7.fhir.r5.conformance.CapabilityStatementUtilities;
|
||||
import org.hl7.fhir.r5.conformance.ProfileComparer;
|
||||
|
@ -14,6 +14,7 @@ import org.hl7.fhir.utilities.TextFile;
|
|||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.cli.utils.Params;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
|
@ -21,7 +22,7 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Comparison {
|
||||
public class ComparisonService {
|
||||
|
||||
public static void doLeftRightComparison(String[] args, String dest, ValidationEngine validator) throws IOException {
|
||||
// ok now set up the comparison
|
||||
|
@ -39,9 +40,9 @@ public class Comparison {
|
|||
|
||||
if (resLeft != null && resRight != null) {
|
||||
if (resLeft instanceof StructureDefinition && resRight instanceof StructureDefinition) {
|
||||
Comparison.compareStructureDefinitions(dest, validator, left, right, (StructureDefinition) resLeft, (StructureDefinition) resRight);
|
||||
ComparisonService.compareStructureDefinitions(dest, validator, left, right, (StructureDefinition) resLeft, (StructureDefinition) resRight);
|
||||
} else if (resLeft instanceof CapabilityStatement && resRight instanceof CapabilityStatement) {
|
||||
Comparison.compareCapabilityStatements(args, dest, validator, left, right, (CanonicalResource) resLeft, (CanonicalResource) resRight);
|
||||
ComparisonService.compareCapabilityStatements(args, dest, validator, left, right, (CanonicalResource) resLeft, (CanonicalResource) resRight);
|
||||
} else
|
||||
System.out.println("Unable to compare left resource " + left + " (" + resLeft.fhirType() + ") with right resource " + right + " (" + resRight.fhirType() + ")");
|
||||
}
|
||||
|
@ -71,7 +72,7 @@ public class Comparison {
|
|||
new JsonParser().setOutputStyle(IParser.OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "CapabilityStatement-intersection.json")), output.getSubset());
|
||||
new JsonParser().setOutputStyle(IParser.OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "OperationOutcome-issues.json")), output.getOutcome());
|
||||
|
||||
String destHtml = Utilities.path(dest, "index.html");
|
||||
String destHtml = Utilities.path(dest, "public/index.html");
|
||||
File htmlFile = new File(destHtml);
|
||||
Desktop.getDesktop().browse(htmlFile.toURI());
|
||||
System.out.println("Done");
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
package org.hl7.fhir.validation.cli.services;
|
||||
|
||||
import org.hl7.fhir.r5.elementmodel.Manager;
|
||||
import org.hl7.fhir.r5.formats.IParser;
|
||||
|
@ -9,6 +9,7 @@ import org.hl7.fhir.r5.utils.ToolingExtensions;
|
|||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.cli.model.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -16,13 +17,37 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ValidationUtils {
|
||||
public class ValidationService {
|
||||
|
||||
public static ValidationResponse validateSources(ValidationRequest request, ValidationEngine validator) throws Exception {
|
||||
if (request.getCliContext().getProfiles().size() > 0) {
|
||||
System.out.println(" .. validate " + request.listSourceFiles() + " against " + request.getCliContext().getProfiles().toString());
|
||||
} else {
|
||||
System.out.println(" .. validate " + request.listSourceFiles());
|
||||
}
|
||||
validator.prepare(); // generate any missing snapshots
|
||||
|
||||
ValidationResponse response = new ValidationResponse();
|
||||
for (FileInfo fp : request.getFilesToValidate()) {
|
||||
OperationOutcome operationOutcome = validator.validate(fp.getFileContent().getBytes(), fp.getFileType(),
|
||||
request.getCliContext().getProfiles());
|
||||
ValidationOutcome outcome = new ValidationOutcome();
|
||||
|
||||
// Need to set file content to null as server can't handle json in json
|
||||
fp.setFileContent(null);
|
||||
outcome.setFileInfo(fp);
|
||||
operationOutcome.getIssue().forEach(outcome::addIssue);
|
||||
response.addOutcome(outcome);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
public static void validateSources(CliContext cliContext, ValidationEngine validator) throws Exception {
|
||||
if (cliContext.getProfiles().size() > 0)
|
||||
if (cliContext.getProfiles().size() > 0) {
|
||||
System.out.println(" .. validate " + cliContext.getSources() + " against " + cliContext.getProfiles().toString());
|
||||
else
|
||||
} else {
|
||||
System.out.println(" .. validate " + cliContext.getSources());
|
||||
}
|
||||
validator.prepare(); // generate any missing snapshots
|
||||
Resource r = validator.validate(cliContext.getSources(), cliContext.getProfiles());
|
||||
int ec = 0;
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
package org.hl7.fhir.validation.cli.utils;
|
||||
|
||||
import org.hl7.fhir.r5.model.Constants;
|
||||
import org.hl7.fhir.r5.model.FhirPublication;
|
||||
|
@ -75,11 +75,9 @@ public class Common {
|
|||
}
|
||||
}
|
||||
|
||||
public static ValidationEngine getValidationEngine(String[] args, String txLog) throws Exception {
|
||||
String v = Common.getVersion(args);
|
||||
String definitions = VersionUtilities.packageForVersion(v) + "#" + v;
|
||||
System.out.println("Loading (v = " + v + ", tx server http://tx.fhir.org)");
|
||||
return new ValidationEngine(definitions, "http://tx.fhir.org", txLog, FhirPublication.fromCode(v), v);
|
||||
public static ValidationEngine getValidationEngine(String version, String definitions, String txLog) throws Exception {
|
||||
System.out.println("Loading (v = " + version + ", tx server http://tx.fhir.org)");
|
||||
return new ValidationEngine(definitions, "http://tx.fhir.org", txLog, FhirPublication.fromCode(version), version);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
package org.hl7.fhir.validation.cli.utils;
|
||||
|
||||
import org.hl7.fhir.r5.model.Constants;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
|
@ -1,7 +1,8 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
package org.hl7.fhir.validation.cli.utils;
|
||||
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.validation.Validator;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
@ -9,6 +10,7 @@ import java.util.Locale;
|
|||
|
||||
public class Params {
|
||||
|
||||
public static final String GUI = "-gui";
|
||||
public static final String VERSION = "-version";
|
||||
public static final String OUTPUT = "-output";
|
||||
public static final String PROXY = "-proxy";
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.validation.cli;
|
||||
package org.hl7.fhir.validation.cli.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="#fff" viewBox="0 180 612 612" focusable="false" role="img">
|
||||
<title>Bootstrap</title>
|
||||
<path d="M510 186c25.5 0 49.6 10 67.8 28.2S606 256.5 606 282v408c0 25.5-10 49.6-28.2 67.8S535.5 786 510 786H102c-25.5 0-49.6-10-67.8-28.2S6 715.5 6 690V282c0-25.5 10-49.6 28.2-67.8S76.5 186 102 186h408m0-6H102C45.9 180 0 225.9 0 282v408c0 56.1 45.9 102 102 102h408c56.1 0 102-45.9 102-102V282c0-56.1-45.9-102-102-102z"/>
|
||||
<path d="M166.3 313h173.5c32 0 57.7 7.3 77 22s29 36.8 29 66.5c0 18-4.4 33.4-13.2 46.2-8.8 12.8-21.4 22.8-37.8 29.8v1c22 4.7 38.7 15.1 50 31.2 11.3 16.2 17 36.4 17 60.8 0 14-2.5 27.1-7.5 39.2-5 12.2-12.8 22.7-23.5 31.5s-24.3 15.8-41 21-36.5 7.8-59.5 7.8h-164V313zm62.5 149.5h102c15 0 27.5-4.2 37.5-12.8s15-20.8 15-36.8c0-18-4.5-30.7-13.5-38s-22-11-39-11h-102v98.6zm0 156.5h110.5c19 0 33.8-4.9 44.2-14.8 10.5-9.8 15.8-23.8 15.8-41.8 0-17.7-5.2-31.2-15.8-40.8s-25.2-14.2-44.2-14.2H228.8V619z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 957 B |
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 58 58" style="enable-background:new 0 0 58 58;" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M33.655,45.988c-0.232-0.31-0.497-0.533-0.793-0.67s-0.608-0.205-0.937-0.205c-0.337,0-0.658,0.063-0.964,0.191
|
||||
s-0.579,0.344-0.82,0.649s-0.431,0.699-0.567,1.183c-0.137,0.483-0.21,1.075-0.219,1.777c0.009,0.684,0.08,1.267,0.212,1.75
|
||||
s0.314,0.877,0.547,1.183s0.497,0.528,0.793,0.67s0.608,0.212,0.937,0.212c0.337,0,0.658-0.066,0.964-0.198s0.579-0.349,0.82-0.649
|
||||
s0.431-0.695,0.567-1.183s0.21-1.082,0.219-1.784c-0.009-0.684-0.08-1.265-0.212-1.743S33.888,46.298,33.655,45.988z"/>
|
||||
<path d="M51.5,39V13.978c0-0.766-0.092-1.333-0.55-1.792L39.313,0.55C38.964,0.201,38.48,0,37.985,0H8.963
|
||||
C7.777,0,6.5,0.916,6.5,2.926V39H51.5z M29.5,33c0,0.552-0.447,1-1,1s-1-0.448-1-1v-3c0-0.552,0.447-1,1-1s1,0.448,1,1V33z
|
||||
M37.5,3.391c0-0.458,0.553-0.687,0.877-0.363l10.095,10.095C48.796,13.447,48.567,14,48.109,14H37.5V3.391z M36.5,24v-4
|
||||
c0-0.551-0.448-1-1-1c-0.553,0-1-0.448-1-1s0.447-1,1-1c1.654,0,3,1.346,3,3v4c0,1.103,0.897,2,2,2c0.553,0,1,0.448,1,1
|
||||
s-0.447,1-1,1c-1.103,0-2,0.897-2,2v4c0,1.654-1.346,3-3,3c-0.553,0-1-0.448-1-1s0.447-1,1-1c0.552,0,1-0.449,1-1v-4
|
||||
c0-1.2,0.542-2.266,1.382-3C37.042,26.266,36.5,25.2,36.5,24z M28.5,22c0.828,0,1.5,0.672,1.5,1.5S29.328,25,28.5,25
|
||||
c-0.828,0-1.5-0.672-1.5-1.5S27.672,22,28.5,22z M16.5,26c1.103,0,2-0.897,2-2v-4c0-1.654,1.346-3,3-3c0.553,0,1,0.448,1,1
|
||||
s-0.447,1-1,1c-0.552,0-1,0.449-1,1v4c0,1.2-0.542,2.266-1.382,3c0.84,0.734,1.382,1.8,1.382,3v4c0,0.551,0.448,1,1,1
|
||||
c0.553,0,1,0.448,1,1s-0.447,1-1,1c-1.654,0-3-1.346-3-3v-4c0-1.103-0.897-2-2-2c-0.553,0-1-0.448-1-1S15.947,26,16.5,26z"/>
|
||||
<path d="M6.5,41v15c0,1.009,1.22,2,2.463,2h40.074c1.243,0,2.463-0.991,2.463-2V41H6.5z M18.021,51.566
|
||||
c0,0.474-0.087,0.873-0.26,1.196s-0.405,0.583-0.697,0.779s-0.627,0.333-1.005,0.41c-0.378,0.077-0.768,0.116-1.169,0.116
|
||||
c-0.2,0-0.436-0.021-0.704-0.062s-0.547-0.104-0.834-0.191s-0.563-0.185-0.827-0.294s-0.487-0.232-0.67-0.369l0.697-1.107
|
||||
c0.091,0.063,0.221,0.13,0.39,0.198s0.354,0.132,0.554,0.191s0.41,0.111,0.629,0.157s0.424,0.068,0.615,0.068
|
||||
c0.483,0,0.868-0.094,1.155-0.28s0.439-0.504,0.458-0.95v-7.711h1.668V51.566z M25.958,52.298c-0.15,0.342-0.362,0.643-0.636,0.902
|
||||
s-0.61,0.467-1.012,0.622s-0.856,0.232-1.367,0.232c-0.219,0-0.444-0.012-0.677-0.034s-0.467-0.062-0.704-0.116
|
||||
c-0.237-0.055-0.463-0.13-0.677-0.226s-0.398-0.212-0.554-0.349l0.287-1.176c0.128,0.073,0.289,0.144,0.485,0.212
|
||||
s0.398,0.132,0.608,0.191s0.419,0.107,0.629,0.144s0.405,0.055,0.588,0.055c0.556,0,0.982-0.13,1.278-0.39s0.444-0.645,0.444-1.155
|
||||
c0-0.31-0.104-0.574-0.314-0.793s-0.472-0.417-0.786-0.595s-0.654-0.355-1.019-0.533s-0.706-0.388-1.025-0.629
|
||||
s-0.583-0.526-0.793-0.854s-0.314-0.738-0.314-1.23c0-0.446,0.082-0.843,0.246-1.189s0.385-0.641,0.663-0.882
|
||||
s0.602-0.426,0.971-0.554s0.759-0.191,1.169-0.191c0.419,0,0.843,0.039,1.271,0.116s0.774,0.203,1.039,0.376
|
||||
c-0.055,0.118-0.118,0.248-0.191,0.39s-0.142,0.273-0.205,0.396s-0.118,0.226-0.164,0.308s-0.073,0.128-0.082,0.137
|
||||
c-0.055-0.027-0.116-0.063-0.185-0.109s-0.166-0.091-0.294-0.137s-0.296-0.077-0.506-0.096s-0.479-0.014-0.807,0.014
|
||||
c-0.183,0.019-0.355,0.07-0.52,0.157s-0.31,0.193-0.438,0.321s-0.228,0.271-0.301,0.431s-0.109,0.313-0.109,0.458
|
||||
c0,0.364,0.104,0.658,0.314,0.882s0.47,0.419,0.779,0.588s0.647,0.333,1.012,0.492s0.704,0.354,1.019,0.581
|
||||
s0.576,0.513,0.786,0.854s0.314,0.781,0.314,1.319C26.184,51.603,26.108,51.956,25.958,52.298z M35.761,51.156
|
||||
c-0.214,0.647-0.511,1.185-0.889,1.613s-0.82,0.752-1.326,0.971s-1.06,0.328-1.661,0.328s-1.155-0.109-1.661-0.328
|
||||
s-0.948-0.542-1.326-0.971s-0.675-0.966-0.889-1.613s-0.321-1.395-0.321-2.242s0.107-1.593,0.321-2.235s0.511-1.178,0.889-1.606
|
||||
s0.82-0.754,1.326-0.978s1.06-0.335,1.661-0.335s1.155,0.111,1.661,0.335s0.948,0.549,1.326,0.978s0.675,0.964,0.889,1.606
|
||||
s0.321,1.388,0.321,2.235S35.975,50.509,35.761,51.156z M45.68,54h-1.668l-3.951-6.945V54h-1.668V43.924h1.668l3.951,6.945v-6.945
|
||||
h1.668V54z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.4 KiB |
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 58 58" style="enable-background:new 0 0 58 58;" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M51.5,39V13.978c0-0.766-0.092-1.333-0.55-1.792L39.313,0.55C38.964,0.201,38.48,0,37.985,0H8.963
|
||||
C7.777,0,6.5,0.916,6.5,2.926V39H51.5z M37.5,3.391c0-0.458,0.553-0.687,0.877-0.363l10.095,10.095
|
||||
C48.796,13.447,48.567,14,48.109,14H37.5V3.391z M33.793,18.707c-0.391-0.391-0.391-1.023,0-1.414s1.023-0.391,1.414,0l6,6
|
||||
c0.391,0.391,0.391,1.023,0,1.414l-6,6C35.012,30.902,34.756,31,34.5,31s-0.512-0.098-0.707-0.293
|
||||
c-0.391-0.391-0.391-1.023,0-1.414L39.086,24L33.793,18.707z M24.557,31.667l6-17c0.185-0.521,0.753-0.795,1.276-0.61
|
||||
c0.521,0.184,0.794,0.755,0.61,1.276l-6,17C26.298,32.744,25.912,33,25.5,33c-0.11,0-0.223-0.019-0.333-0.058
|
||||
C24.646,32.759,24.373,32.188,24.557,31.667z M15.793,23.293l6-6c0.391-0.391,1.023-0.391,1.414,0s0.391,1.023,0,1.414L17.914,24
|
||||
l5.293,5.293c0.391,0.391,0.391,1.023,0,1.414C23.012,30.902,22.756,31,22.5,31s-0.512-0.098-0.707-0.293l-6-6
|
||||
C15.402,24.316,15.402,23.684,15.793,23.293z"/>
|
||||
<path d="M6.5,41v15c0,1.009,1.22,2,2.463,2h40.074c1.243,0,2.463-0.991,2.463-2V41H6.5z M22.936,54h-1.9l-1.6-3.801h-0.137
|
||||
L17.576,54h-1.9l2.557-4.895l-2.721-5.182h1.873l1.777,4.102h0.137l1.928-4.102H23.1l-2.721,5.182L22.936,54z M34.666,54h-1.668
|
||||
v-6.932l-2.256,5.605h-1.449l-2.27-5.605V54h-1.668V43.924h1.668l2.994,6.891l2.98-6.891h1.668V54z M43.498,54h-6.303V43.924h1.668
|
||||
v8.832h4.635V54z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,56 @@
|
|||
<!--aside id="sidebar">
|
||||
<div class="">
|
||||
<label>Validation Options</label>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="doNative">doNative</li>
|
||||
<li><input type="checkbox" id="anyExtensionAllowed">anyExtensionAllowed</li>
|
||||
<li><input type="checkbox" id="hintAboutNonMustSupport">hintAboutNonMustSupport</li>
|
||||
<li><input type="checkbox" id="recursive">recursive</li>
|
||||
<li><input type="checkbox" id="doDebug">doDebug</li>
|
||||
<li><input type="checkbox" id="assumeValidRestReferences">assumeValidRestReferences</li>
|
||||
<li><input type="checkbox" name="canDoNative" id="canDoNative">canDoNative</li>
|
||||
|
||||
<li>
|
||||
<label>Map</label>
|
||||
<input type="text" name="map" placeholder="enter map">
|
||||
</li>
|
||||
<li>
|
||||
<label>Output</label>
|
||||
<input type="text" name="output" placeholder="enter output">
|
||||
</li>
|
||||
<li>
|
||||
<label>txServer</label>
|
||||
<input type="text" name="txServer" placeholder="enter txServer">
|
||||
</li>
|
||||
<li>
|
||||
<label>sv</label>
|
||||
<input type="text" name="sv" placeholder="enter sv">
|
||||
</li>
|
||||
<li>
|
||||
<label>txLog</label>
|
||||
<input type="text" name="txLog" placeholder="enter txLog">
|
||||
</li>
|
||||
<li>
|
||||
<label>mapLog</label>
|
||||
<input type="text" name="mapLog" placeholder="enter mapLog">
|
||||
</li>
|
||||
<li>
|
||||
<label>lang</label>
|
||||
<input type="text" name="lang" placeholder="enter lang">
|
||||
</li>
|
||||
<li>
|
||||
<label>fhirpath</label>
|
||||
<input type="text" name="fhirpath" placeholder="enter fhirpath">
|
||||
</li>
|
||||
<li>
|
||||
<label>snomedCT</label>
|
||||
<input type="text" name="snomedCT" placeholder="enter snomedCT">
|
||||
</li>
|
||||
<li>
|
||||
<label>targetVer</label>
|
||||
<input type="text" name="targetVer" placeholder="enter targetVer">
|
||||
</li>
|
||||
</ul>
|
||||
<input id='test_button' class="btn" type="submit" value="Submit">
|
||||
</div>
|
||||
</aside-->
|
|
@ -0,0 +1,10 @@
|
|||
export const EngineMode {
|
||||
VALIDATION,
|
||||
TRANSFORM,
|
||||
NARRATIVE,
|
||||
SNAPSHOT,
|
||||
SCAN,
|
||||
CONVERT,
|
||||
FHIRPATH,
|
||||
VERSION
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
export const FhirFormat = {
|
||||
XML: {
|
||||
extension:'xml'
|
||||
},
|
||||
JSON: {
|
||||
extension:'json'
|
||||
},
|
||||
TURTLE: {
|
||||
extension:'ttl'
|
||||
},
|
||||
TEXT: {
|
||||
extension:'txt'
|
||||
},
|
||||
VBAR: {
|
||||
extension:'hl7'
|
||||
},
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
export const Locale = {
|
||||
ENGLISH: {
|
||||
code: 'en',
|
||||
value: 'English'
|
||||
},
|
||||
FRENCH: {
|
||||
code: 'fr',
|
||||
value: 'French'
|
||||
},
|
||||
GERMAN: {
|
||||
code: 'de',
|
||||
value: 'German'
|
||||
},
|
||||
ITALIAN: {
|
||||
code: 'it',
|
||||
value: 'Italian'
|
||||
},
|
||||
JAPANESE: {
|
||||
code: 'ja',
|
||||
value: 'Japanese'
|
||||
},
|
||||
KOREAN: {
|
||||
code: 'ko',
|
||||
value: 'Korean'
|
||||
},
|
||||
CHINESE: {
|
||||
code: 'zh',
|
||||
value: 'Chinese'
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
export const SnomedVersion = {
|
||||
INTL: {
|
||||
value: "intl",
|
||||
code: "900000000000207008"
|
||||
},
|
||||
US: {
|
||||
value: "us",
|
||||
code: "731000124108"
|
||||
},
|
||||
UK: {
|
||||
value: "uk",
|
||||
code: "999000041000000102"
|
||||
},
|
||||
AU: {
|
||||
value: "au",
|
||||
code: "32506021000036107"
|
||||
},
|
||||
CA: {
|
||||
value: "ca",
|
||||
code: "20611000087101"
|
||||
},
|
||||
NL: {
|
||||
value: "nl",
|
||||
code: "11000146104"
|
||||
},
|
||||
SE: {
|
||||
value: "se",
|
||||
code: "45991000052106"
|
||||
},
|
||||
ES: {
|
||||
value: "es",
|
||||
code: "449081005"
|
||||
},
|
||||
DK: {
|
||||
value: "dk",
|
||||
code: "554471000005108"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>JS For Beginners</title>
|
||||
<!-- link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"-->
|
||||
|
||||
<!-- Compiled and minified JavaScript -->
|
||||
<!--link rel="stylesheet" href="style.css"-->
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Validator 2.0</h1>
|
||||
</header>
|
||||
<div class="container">
|
||||
<section id="main">
|
||||
<div class="">
|
||||
<ul>
|
||||
<li class="line1">
|
||||
<text></text>
|
||||
<button class="delete_button"></button>
|
||||
</li>
|
||||
<li class="line1">
|
||||
<text>Filename Here</text>
|
||||
<svg class="delete_button" height="24" viewBox="0 0 24 24" width="24">
|
||||
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/>
|
||||
</svg>
|
||||
</li>
|
||||
</ul>
|
||||
<button id="add_file_button" type="button" name="button">Add File</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input type="file" style="display:none;" id="files" name="files[]" multiple />
|
||||
<input type="button" id="loadFileXml" value="Add File Please" onclick="document.getElementById('files').click()" />
|
||||
<ul id="list"></ul>
|
||||
</div>
|
||||
|
||||
<template id="file_entry">
|
||||
<li>
|
||||
<details>
|
||||
<summary>
|
||||
<span id="file_name_field" class="summary-title">asdasdasd</span>
|
||||
<div class="summary-chevron-up">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
||||
</div>
|
||||
</summary>
|
||||
<div id="file_content_field" class="summary-content">asdasdasdas</div>
|
||||
<div class="summary-chevron-down">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-up"><polyline points="18 15 12 9 6 15"></polyline></svg>
|
||||
</details>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
<footer id="main-footer">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
</footer>
|
||||
<script type="module" src="./main.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,133 @@
|
|||
import {CliContext} from './model/CliContext.js';
|
||||
import {ValidationRequest} from './model/ValidationRequest.js';
|
||||
import {FileInfo} from './model/FileInfo.js';
|
||||
|
||||
// Constants
|
||||
const jsonIcon = './assets/json-svgrepo-com.svg';
|
||||
const xmlIcon = './assets/xml-svgrepo-com.svg';
|
||||
|
||||
// Data Fields
|
||||
const cli = new CliContext();
|
||||
const filesToValidate = [];
|
||||
|
||||
document.getElementById('validate_button').addEventListener("click", validateCurrentFiles);
|
||||
document.getElementById('files').addEventListener('change', handleFileSelect, false);
|
||||
|
||||
// File reading
|
||||
function handleFileSelect(evt) {
|
||||
var files = evt.target.files;
|
||||
var output = [];
|
||||
for (var i = 0, f; f = files[i]; i++) {
|
||||
generateFileEntry(f);
|
||||
// Check for proper file type here
|
||||
console.log(f.type);
|
||||
}
|
||||
}
|
||||
|
||||
function generateFileEntry(file) {
|
||||
var fr = new FileReader();
|
||||
fr.onload = function(e) {
|
||||
// TODO there may be timing issues here
|
||||
filesToValidate.push(new FileInfo(file.name, e.target.result, file.type));
|
||||
document.getElementById('loaded_file_list').appendChild(generateNewFileListItemFromTemplate(file));
|
||||
};
|
||||
fr.readAsText(file);
|
||||
}
|
||||
|
||||
// File List Template Generation
|
||||
|
||||
function generateNewFileListItemFromTemplate(file) {
|
||||
var template = document.querySelector('#loaded_file_entry');
|
||||
var clone = template.content.cloneNode(true);
|
||||
|
||||
// Add file name
|
||||
clone.getElementById('file_name_field').textContent = file.name;
|
||||
|
||||
// Add appropriate icon for filetype
|
||||
if (file.type.includes("json")) {
|
||||
clone.getElementById('file_type_icon').src = jsonIcon;
|
||||
} else if (file.type.includes("xml")) {
|
||||
clone.getElementById('file_type_icon').src = xmlIcon;
|
||||
}
|
||||
|
||||
// Add delete listener
|
||||
clone.getElementById("delete_button").addEventListener("click", handleDeleteOnFileList);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
function handleDeleteOnFileList(e) {
|
||||
var li = e.target.closest('li');
|
||||
var nodes = Array.from( li.closest('ul').children );
|
||||
var index = nodes.indexOf( li );
|
||||
nodes[index].remove();
|
||||
filesToValidate.splice((index - 1), 1);
|
||||
console.log('Index -> ' + index);
|
||||
console.log(filesToValidate);
|
||||
}
|
||||
|
||||
// Validation
|
||||
function validateCurrentFiles() {
|
||||
sendFilesToValidate(filesToValidate);
|
||||
}
|
||||
|
||||
function sendFilesToValidate(arrayOfFileInfo) {
|
||||
var req = new ValidationRequest();
|
||||
req.filesToValidate = arrayOfFileInfo;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", 'http://localhost:8080/' + 'validate', true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(JSON.stringify(req));
|
||||
|
||||
xhr.onload = function () {
|
||||
const response = '{"outcomes": [{"fileInfo": {"fileName": "account-example.canonical.json", "fileType": "JSON"}, "issues": [{"severity": "Error", "details": "\"null\""}, {"severity": "Error", "details": "Profile http://hl7.org/fhir/StructureDefinition/Account, Element: minimum required = 1, but only found 0"}]}, {"fileInfo": {"fileName": "account-example(example).xml", "fileType": "XML"}, "issues": []}]}';
|
||||
var test = xhr.responseText;
|
||||
processValidationResponse(JSON.parse(JSON.parse(xhr.responseText)));
|
||||
};
|
||||
}
|
||||
|
||||
function processValidationResponse(validationResponse) {
|
||||
console.log(validationResponse.outcomes[0]);
|
||||
console.log(validationResponse.outcomes[1]);
|
||||
//console.log(validationResponse);
|
||||
//Do something
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// window.onload = function loadCliContext() {
|
||||
// var xhr = new XMLHttpRequest();
|
||||
// xhr.open("GET", 'http://localhost:8080/currentContext');
|
||||
// xhr.send();
|
||||
// xhr.onreadystatechange = function() {
|
||||
// if (this.readyState == 4 && this.status == 200) {
|
||||
// console.log(xhr.responseText);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// /*
|
||||
// Escape JSON
|
||||
// */
|
||||
// var escapeJSON = exports.escapeJSON = function(json) {
|
||||
// var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
|
||||
// var meta = { // table of character substitutions
|
||||
// '\b': '\\b',
|
||||
// '\t': '\\t',
|
||||
// '\n': '\\n',
|
||||
// '\f': '\\f',
|
||||
// '\r': '\\r',
|
||||
// '"' : '\\"',
|
||||
// '\\': '\\\\'
|
||||
// };
|
||||
//
|
||||
// escapable.lastIndex = 0;
|
||||
// return escapable.test(json) ? '"' + json.replace(escapable, function (a) {
|
||||
// var c = meta[a];
|
||||
// return (typeof c === 'string') ? c
|
||||
// : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
// }) + '"' : '"' + json + '"';
|
||||
//
|
||||
// };
|
|
@ -0,0 +1,34 @@
|
|||
import {SnomedVersion} from '../enums/SnomedVersion.js';
|
||||
import {Locale} from '../enums/Locale.js';
|
||||
|
||||
export class CliContext {
|
||||
constructor(){
|
||||
this.doNative = false;
|
||||
this.anyExtensionsAllowed = true;
|
||||
this.hintAboutNonMustSupport = false;
|
||||
this.recursive = false;
|
||||
this.doDebug = false;
|
||||
this.assumeValidRestReferences = false;
|
||||
this.canDoNative = false;
|
||||
|
||||
this.map = null;
|
||||
this.output = null;
|
||||
this.txServer = "http://tx.fhir.org";
|
||||
this.sv = "current";
|
||||
this.txLog = null;
|
||||
this.mapLog = null;
|
||||
this.lang = null;
|
||||
this.fhirpath = null;
|
||||
this.snomedCT = SnomedVersion.ES.value;
|
||||
this.targetVer = null;
|
||||
|
||||
this.igs = [];
|
||||
this.questionnaires = [];
|
||||
this.profiles = [];
|
||||
this.sources = [];
|
||||
|
||||
this.locale = Locale.ENGLISH.value;
|
||||
|
||||
this.locations = new Map();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import {FhirFormat} from '../enums/FhirFormat.js';
|
||||
|
||||
export class FileInfo {
|
||||
constructor(fileName, fileContent, type){
|
||||
this.fileName = fileName;
|
||||
this.fileContent = fileContent;
|
||||
if (type.includes('json')) {
|
||||
this.fileType = FhirFormat.JSON.extension;
|
||||
} else if (type.includes('xml')) {
|
||||
this.fileType = FhirFormat.XML.extension;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export class ValidationIssue {
|
||||
constructor(){
|
||||
this.severity = "";
|
||||
this.details = "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import {FileInfo} from './FileInfo.js';
|
||||
|
||||
export class ValidationOutcome {
|
||||
constructor(){
|
||||
this.fileInfo = null;
|
||||
this.issues = [];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import {CliContext} from './CliContext.js';
|
||||
|
||||
export class ValidationRequest {
|
||||
constructor(){
|
||||
this.cliContext = new CliContext();
|
||||
this.filesToValidate = [];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import {ValidationOutcome} from './ValidationOutcome.js';
|
||||
|
||||
export class ValidationResponse {
|
||||
constructor() {
|
||||
this.outcomes = [];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/* */
|
||||
.container{
|
||||
width:80%;
|
||||
margin:auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#main{
|
||||
float: left;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
#sidebar{
|
||||
float: right;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
|
||||
html,
|
||||
body {
|
||||
overflow-x: hidden; /* Prevent scroll on narrow devices */
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: 56px;
|
||||
}
|
||||
|
||||
@media (max-width: 991.98px) {
|
||||
.offcanvas-collapse {
|
||||
position: fixed;
|
||||
top: 56px; /* Height of navbar */
|
||||
bottom: 0;
|
||||
left: 100%;
|
||||
width: 100%;
|
||||
padding-right: 1rem;
|
||||
padding-left: 1rem;
|
||||
overflow-y: auto;
|
||||
visibility: hidden;
|
||||
background-color: #343a40;
|
||||
transition: visibility .3s ease-in-out, -webkit-transform .3s ease-in-out;
|
||||
transition: transform .3s ease-in-out, visibility .3s ease-in-out;
|
||||
transition: transform .3s ease-in-out, visibility .3s ease-in-out, -webkit-transform .3s ease-in-out;
|
||||
}
|
||||
.offcanvas-collapse.open {
|
||||
visibility: visible;
|
||||
-webkit-transform: translateX(-100%);
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-scroller {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
height: 2.75rem;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.nav-scroller .nav {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
padding-bottom: 1rem;
|
||||
margin-top: -1px;
|
||||
overflow-x: auto;
|
||||
color: rgba(255, 255, 255, .75);
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.nav-underline .nav-link {
|
||||
padding-top: .75rem;
|
||||
padding-bottom: .75rem;
|
||||
font-size: .875rem;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.nav-underline .nav-link:hover {
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.nav-underline .active {
|
||||
font-weight: 500;
|
||||
color: #343a40;
|
||||
}
|
||||
|
||||
.text-white-50 { color: rgba(255, 255, 255, .5); }
|
||||
|
||||
.bg-purple { background-color: #6f42c1; }
|
||||
|
||||
.lh-100 { line-height: 1; }
|
||||
.lh-125 { line-height: 1.25; }
|
||||
.lh-150 { line-height: 1.5; }
|
|
@ -0,0 +1,154 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="Mark Iantorno">
|
||||
<meta name="generator" content="Jekyll v3.8.6">
|
||||
<title>FHIR HL7 Resrouce Validator GUI</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
|
||||
<link rel="canonical" href="https://getbootstrap.com/docs/4.4/examples/offcanvas/">
|
||||
<!-- Favicons -->
|
||||
<meta name="theme-color" content="#563d7c">
|
||||
|
||||
<style>
|
||||
.bd-placeholder-img {
|
||||
font-size: 1.125rem;
|
||||
text-anchor: middle;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.bd-placeholder-img-lg {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="style.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
<main role="main" class="container">
|
||||
<div class="d-flex align-items-center p-3 my-3 text-white-50 bg-secondary rounded shadow-sm">
|
||||
<img class="mr-3" src="./assets/fhir-logo-www.png" alt="" height="48">
|
||||
<div class="lh-100">
|
||||
<h6 class="mb-0 text-white lh-100">FHIR Core Validator</h6>
|
||||
<small class="text-white">Experimental</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-3 p-3 bg-white rounded shadow-sm">
|
||||
<div class="d-flex border-bottom border-gray justify-content-between align-items-center w-100">
|
||||
<h6 class="pb-2 mb-0">Files to Validate</h6>
|
||||
<button id="validate_button" class="btn btn-secondary mb-1">Validate</button>
|
||||
</div>
|
||||
|
||||
<ul id="loaded_file_list">
|
||||
<template id="loaded_file_entry">
|
||||
<li class="media text-muted pt-3">
|
||||
<img id="file_type_icon" class="bd-placeholder-img mr-2 rounded" src="./assets/json-svgrepo-com.svg" width="32" height="32" preserveAspectRatio="xMidYMid slice">
|
||||
<div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
|
||||
<div class="d-flex justify-content-between align-items-center w-100">
|
||||
<strong class="text-gray-dark" id="file_name_field"></strong>
|
||||
<svg id="delete_button" class="delete_button" height="24" viewBox="0 0 24 24" width="24">
|
||||
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="d-block"></span>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
|
||||
<div class="bd-callout bd-callout-info">
|
||||
<small class="d-block text-right mt-3">
|
||||
<input type="file" style="display:none;" id="files" name="files[]" multiple />
|
||||
<button type="button" class="btn btn-secondary" onclick="document.getElementById('files').click()">Add Files</button>
|
||||
</small>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="card z-depth-0 bordered">
|
||||
<div class="card-header" id="headingOne">
|
||||
<h5 class="mb-0">
|
||||
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#collapseOne"
|
||||
aria-expanded="true" aria-controls="collapseOne">
|
||||
Collapsible Group Item #1
|
||||
</button>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="collapseOne" class="collapse show" aria-labelledby="headingOne"
|
||||
data-parent="#accordionExample">
|
||||
<div class="card-body">
|
||||
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3
|
||||
wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum
|
||||
eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla
|
||||
assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred
|
||||
nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer
|
||||
farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus
|
||||
labore sustainable.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card z-depth-0 bordered">
|
||||
<div class="card-header" id="headingTwo">
|
||||
<h5 class="mb-0">
|
||||
<button class="btn btn-link collapsed" type="button" data-toggle="collapse"
|
||||
data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
|
||||
Collapsible Group Item #2
|
||||
</button>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionExample">
|
||||
<div class="card-body">
|
||||
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3
|
||||
wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum
|
||||
eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla
|
||||
assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred
|
||||
nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer
|
||||
farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus
|
||||
labore sustainable.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card z-depth-0 bordered">
|
||||
<div class="card-header" id="headingThree">
|
||||
<h5 class="mb-0">
|
||||
<button class="btn btn-link collapsed" type="button" data-toggle="collapse"
|
||||
data-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
|
||||
Collapsible Group Item #3
|
||||
</button>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="collapseThree" class="collapse" aria-labelledby="headingThree" data-parent="#accordionExample">
|
||||
<div class="card-body">
|
||||
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3
|
||||
wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum
|
||||
eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla
|
||||
assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred
|
||||
nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer
|
||||
farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus
|
||||
labore sustainable.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
<script type="module" src="./main.js"></script>
|
||||
|
||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue