Merge pull request #1426 from hapifhir/2023-09-gg-imposes-profile

2023 09 gg imposes profile
This commit is contained in:
Grahame Grieve 2023-09-06 02:56:35 +10:00 committed by GitHub
commit 8d8e6e188e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 103 additions and 23 deletions

View File

@ -1,5 +1,8 @@
package org.hl7.fhir.convertors.analytics; package org.hl7.fhir.convertors.analytics;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -42,7 +45,8 @@ public class PackageVisitor {
private boolean current; private boolean current;
private IPackageVisitorProcessor processor; private IPackageVisitorProcessor processor;
private FilesystemPackageCacheManager pcm; private FilesystemPackageCacheManager pcm;
private PackageClient pc; private PackageClient pc;
private String cache;
public List<String> getResourceTypes() { public List<String> getResourceTypes() {
return resourceTypes; return resourceTypes;
@ -76,6 +80,14 @@ public class PackageVisitor {
public String getCache() {
return cache;
}
public void setCache(String cache) {
this.cache = cache;
}
public void setCorePackages(boolean corePackages) { public void setCorePackages(boolean corePackages) {
this.corePackages = corePackages; this.corePackages = corePackages;
} }
@ -109,6 +121,8 @@ public class PackageVisitor {
System.out.println("Finding packages"); System.out.println("Finding packages");
pc = new PackageClient(PackageServer.primaryServer()); pc = new PackageClient(PackageServer.primaryServer());
pcm = new FilesystemPackageCacheManager(org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager.FilesystemPackageCacheMode.USER); pcm = new FilesystemPackageCacheManager(org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager.FilesystemPackageCacheMode.USER);
Set<String> pidList = getAllPackages();
Map<String, String> cpidMap = getAllCIPackages(); Map<String, String> cpidMap = getAllCIPackages();
Set<String> cpidSet = new HashSet<>(); Set<String> cpidSet = new HashSet<>();
@ -118,7 +132,7 @@ public class PackageVisitor {
processCurrentPackage(s, cpidMap.get(s), cpidSet, i, cpidMap.size()); processCurrentPackage(s, cpidMap.get(s), cpidSet, i, cpidMap.size());
i++; i++;
} }
Set<String> pidList = getAllPackages();
System.out.println("Go: "+pidList.size()+" published packages"); System.out.println("Go: "+pidList.size()+" published packages");
i = 0; i = 0;
for (String pid : pidList) { for (String pid : pidList) {
@ -161,11 +175,21 @@ public class PackageVisitor {
private void processCurrentPackage(String url, String pid, Set<String> cpidSet, int i, int t) { private void processCurrentPackage(String url, String pid, Set<String> cpidSet, int i, int t) {
try { try {
long ms1 = System.currentTimeMillis();
String[] p = url.split("\\/"); String[] p = url.split("\\/");
String repo = "https://build.fhir.org/ig/"+p[0]+"/"+p[1]; String repo = "https://build.fhir.org/ig/"+p[0]+"/"+p[1];
NpmPackage npm = NpmPackage.fromUrl(repo+"/package.tgz"); JsonObject manifest = JsonParser.parseObjectFromUrl(repo+"/package.manifest.json");
File co = new File(Utilities.path(cache, pid+"."+manifest.asString("date")+".tgz"));
if (!co.exists()) {
SimpleHTTPClient fetcher = new SimpleHTTPClient();
HTTPResult res = fetcher.get(repo+"/package.tgz?nocache=" + System.currentTimeMillis());
res.checkThrowException();
TextFile.bytesToFile(res.getContent(), co);
}
NpmPackage npm = NpmPackage.fromPackage(new FileInputStream(co));
String fv = npm.fhirVersion(); String fv = npm.fhirVersion();
cpidSet.add(pid); cpidSet.add(pid);
long ms2 = System.currentTimeMillis();
if (corePackages || !corePackage(npm)) { if (corePackages || !corePackage(npm)) {
int c = 0; int c = 0;
@ -182,7 +206,7 @@ public class PackageVisitor {
} }
} }
} }
System.out.println("Processed: "+pid+"#current: "+c+" resources ("+i+" of "+t+")"); System.out.println("Processed: "+pid+"#current: "+c+" resources ("+i+" of "+t+", "+(ms2-ms1)+"/"+(System.currentTimeMillis()-ms2)+"ms)");
} }
} catch (Exception e) { } catch (Exception e) {
System.out.println("Unable to process: "+pid+"#current: "+e.getMessage()); System.out.println("Unable to process: "+pid+"#current: "+e.getMessage());

View File

@ -2839,10 +2839,11 @@ public class ProfileUtilities extends TranslatingUtilities {
boolean ok = false; boolean ok = false;
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
String t = ts.getWorkingCode(); String t = ts.getWorkingCode();
String tDesc = ts.toString();
for (TypeRefComponent td : base.getType()) {; for (TypeRefComponent td : base.getType()) {;
boolean matchType = false; boolean matchType = false;
String tt = td.getWorkingCode(); String tt = td.getWorkingCode();
b.append(tt); b.append(td.toString());
if (td.hasCode() && (tt.equals(t))) { if (td.hasCode() && (tt.equals(t))) {
matchType = true; matchType = true;
} }
@ -2869,20 +2870,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// check that any derived target has a reference chain back to one of the base target profiles // check that any derived target has a reference chain back to one of the base target profiles
for (UriType u : ts.getTargetProfile()) { for (UriType u : ts.getTargetProfile()) {
String url = u.getValue(); String url = u.getValue();
boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url); boolean tgtOk = !td.hasTargetProfile() || sdConformsToTargets(path, derived.getPath(), url, td);
while (url != null && !tgtOk) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
if (sd == null) {
if (messages != null) {
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, path, "Cannot check whether the target profile " + url + " on "+derived.getPath()+" is valid constraint on the base because it is not known", IssueSeverity.WARNING));
}
url = null;
tgtOk = true; // suppress error message
} else {
url = sd.getBaseDefinition();
tgtOk = td.hasTargetProfile(url);
}
}
if (tgtOk) { if (tgtOk) {
ok = true; ok = true;
} else { } else {
@ -2899,11 +2887,34 @@ public class ProfileUtilities extends TranslatingUtilities {
} }
} }
if (!ok) { if (!ok) {
throw new DefinitionException(context.formatMessage(I18nConstants.STRUCTUREDEFINITION__AT__ILLEGAL_CONSTRAINED_TYPE__FROM__IN_, purl, derived.getPath(), t, b.toString(), srcSD.getUrl())); throw new DefinitionException(context.formatMessage(I18nConstants.STRUCTUREDEFINITION__AT__ILLEGAL_CONSTRAINED_TYPE__FROM__IN_, purl, derived.getPath(), tDesc, b.toString(), srcSD.getUrl()));
} }
} }
private boolean sdConformsToTargets(String path, String dPath, String url, TypeRefComponent td) {
if (td.hasTargetProfile(url)) {
return true;
}
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
if (sd == null) {
if (messages != null) {
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, path, "Cannot check whether the target profile " + url + " on "+dPath+" is valid constraint on the base because it is not known", IssueSeverity.WARNING));
}
return true;
} else {
if (sd.hasBaseDefinition() && sdConformsToTargets(path, dPath, sd.getBaseDefinition(), td)) {
return true;
}
for (Extension ext : sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_IMPOSE_PROFILE)) {
if (sdConformsToTargets(path, dPath, ext.getValueCanonicalType().asStringValue(), td)) {
return true;
}
}
}
return false;
}
private void checkTypeOk(ElementDefinition dest, String ft, StructureDefinition sd, String fieldName) { private void checkTypeOk(ElementDefinition dest, String ft, StructureDefinition sd, String fieldName) {
boolean ok = false; boolean ok = false;
Set<String> types = new HashSet<>(); Set<String> types = new HashSet<>();

View File

@ -2587,7 +2587,7 @@ public boolean hasTarget() {
res = res + "}"; res = res + "}";
} }
if (hasTargetProfile()) { if (hasTargetProfile()) {
res = res + "->("; res = res + "(";
boolean first = true; boolean first = true;
for (CanonicalType s : getTargetProfile()) { for (CanonicalType s : getTargetProfile()) {
if (first) first = false; else res = res + "|"; if (first) first = false; else res = res + "|";

View File

@ -42,6 +42,7 @@ import org.commonmark.node.Node;
import org.commonmark.parser.Parser; import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.renderer.html.HtmlRenderer;
import com.github.rjeschke.txtmark.Configuration;
import com.github.rjeschke.txtmark.Processor; import com.github.rjeschke.txtmark.Processor;
public class MarkDownProcessor { public class MarkDownProcessor {
@ -65,7 +66,8 @@ public class MarkDownProcessor {
return ""; return "";
} }
switch (dialect) { switch (dialect) {
case DARING_FIREBALL : return Processor.process(source); case DARING_FIREBALL :
return Processor.process(source, Configuration.builder().enableSafeMode().enablePanicMode().build());
case COMMON_MARK : return processCommonMark(preProcess(source)); case COMMON_MARK : return processCommonMark(preProcess(source));
default: throw new Error("Unknown Markdown Dialect: "+dialect.toString()+" at "+context); default: throw new Error("Unknown Markdown Dialect: "+dialect.toString()+" at "+context);
} }

View File

@ -647,6 +647,10 @@ public class Utilities {
return PathBuilder.getPathBuilder().buildPath(args); return PathBuilder.getPathBuilder().buildPath(args);
} }
public static File pathFile(String... args) throws IOException {
return new File(PathBuilder.getPathBuilder().buildPath(args));
}
public static String path(File f, String... args) throws IOException { public static String path(File f, String... args) throws IOException {
String[] a = new String[args.length+1]; String[] a = new String[args.length+1];
a[0] = f.getAbsolutePath(); a[0] = f.getAbsolutePath();

View File

@ -1,6 +1,7 @@
package org.hl7.fhir.utilities.json.parser; package org.hl7.fhir.utilities.json.parser;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -167,6 +168,12 @@ public class JsonParser {
compose(element, stream, false); compose(element, stream, false);
} }
public static void compose(JsonElement element, File file) throws IOException {
FileOutputStream fo = new FileOutputStream(file);
compose(element, fo, false);
fo.close();
}
public static byte[] composeBytes(JsonElement element) { public static byte[] composeBytes(JsonElement element) {
return composeBytes(element, false); return composeBytes(element, false);
} }
@ -179,6 +186,12 @@ public class JsonParser {
byte[] cnt = composeBytes(element, pretty); byte[] cnt = composeBytes(element, pretty);
stream.write(cnt); stream.write(cnt);
} }
public static void compose(JsonElement element, File file, boolean pretty) throws IOException {
byte[] cnt = composeBytes(element, pretty);
FileOutputStream fo = new FileOutputStream(file);
fo.write(cnt);
fo.close();
}
public static byte[] composeBytes(JsonElement element, boolean pretty) { public static byte[] composeBytes(JsonElement element, boolean pretty) {
String s = compose(element, pretty); String s = compose(element, pretty);

View File

@ -5,7 +5,9 @@ import java.io.IOException;
import java.text.ParseException; import java.text.ParseException;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.hl7.fhir.utilities.FhirPublication; import org.hl7.fhir.utilities.FhirPublication;
import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.TextFile;
@ -67,6 +69,10 @@ public class PackageList {
json.set("date", date); json.set("date", date);
} }
public String name() {
return json.asString("name");
}
public List<String> subPackages() { public List<String> subPackages() {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
if (json.has("sub-packages")) { if (json.has("sub-packages")) {
@ -169,6 +175,7 @@ public class PackageList {
} }
setDate(date); setDate(date);
} }
} }
private String source; private String source;
@ -334,5 +341,15 @@ public class PackageList {
return json.asString("introduction"); return json.asString("introduction");
} }
public List<PackageListEntry> milestones() {
List<PackageListEntry> list = new ArrayList<>();
for (PackageListEntry t : versions) {
if (t.name() != null) {
list.add(t);
}
}
return list;
}
} }

View File

@ -47,6 +47,7 @@ import java.util.Set;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.utilities.StringPair; import org.hl7.fhir.utilities.StringPair;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.xhtml.XhtmlNode.Location; import org.hl7.fhir.utilities.xhtml.XhtmlNode.Location;
@ -59,6 +60,7 @@ import org.xmlpull.v1.XmlPullParserException;
public class XhtmlParser { public class XhtmlParser {
public static final String XHTML_NS = "http://www.w3.org/1999/xhtml"; public static final String XHTML_NS = "http://www.w3.org/1999/xhtml";
private static final char END_OF_CHARS = (char) -1; private static final char END_OF_CHARS = (char) -1;
private static final boolean DEBUG = false;
public class NamespaceNormalizationMap { public class NamespaceNormalizationMap {
@ -1285,7 +1287,14 @@ public class XhtmlParser {
public XhtmlNode parseFragment(String source) throws IOException, FHIRException { public XhtmlNode parseFragment(String source) throws IOException, FHIRException {
rdr = new StringReader(source); rdr = new StringReader(source);
return parseFragment(); try {
return parseFragment();
} catch (Exception e) {
if (DEBUG) {
TextFile.stringToFile(source, Utilities.path("[tmp]", "html-fail.xhtml"));
}
throw e;
}
} }
public XhtmlNode parseFragment(InputStream input) throws IOException, FHIRException { public XhtmlNode parseFragment(InputStream input) throws IOException, FHIRException {