rework type checking on target profiles to support imposesProfile
This commit is contained in:
parent
cdda99c290
commit
beb89b575a
|
@ -1,5 +1,8 @@
|
|||
package org.hl7.fhir.convertors.analytics;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -43,6 +46,7 @@ public class PackageVisitor {
|
|||
private IPackageVisitorProcessor processor;
|
||||
private FilesystemPackageCacheManager pcm;
|
||||
private PackageClient pc;
|
||||
private String cache;
|
||||
|
||||
public List<String> getResourceTypes() {
|
||||
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) {
|
||||
this.corePackages = corePackages;
|
||||
}
|
||||
|
@ -110,6 +122,8 @@ public class PackageVisitor {
|
|||
pc = new PackageClient(PackageServer.primaryServer());
|
||||
pcm = new FilesystemPackageCacheManager(org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager.FilesystemPackageCacheMode.USER);
|
||||
|
||||
Set<String> pidList = getAllPackages();
|
||||
|
||||
Map<String, String> cpidMap = getAllCIPackages();
|
||||
Set<String> cpidSet = new HashSet<>();
|
||||
System.out.println("Go: "+cpidMap.size()+" current packages");
|
||||
|
@ -118,7 +132,7 @@ public class PackageVisitor {
|
|||
processCurrentPackage(s, cpidMap.get(s), cpidSet, i, cpidMap.size());
|
||||
i++;
|
||||
}
|
||||
Set<String> pidList = getAllPackages();
|
||||
|
||||
System.out.println("Go: "+pidList.size()+" published packages");
|
||||
i = 0;
|
||||
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) {
|
||||
try {
|
||||
long ms1 = System.currentTimeMillis();
|
||||
String[] p = url.split("\\/");
|
||||
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();
|
||||
cpidSet.add(pid);
|
||||
long ms2 = System.currentTimeMillis();
|
||||
|
||||
if (corePackages || !corePackage(npm)) {
|
||||
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) {
|
||||
System.out.println("Unable to process: "+pid+"#current: "+e.getMessage());
|
||||
|
|
|
@ -2839,10 +2839,11 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
boolean ok = false;
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
String t = ts.getWorkingCode();
|
||||
String tDesc = ts.toString();
|
||||
for (TypeRefComponent td : base.getType()) {;
|
||||
boolean matchType = false;
|
||||
String tt = td.getWorkingCode();
|
||||
b.append(tt);
|
||||
b.append(td.toString());
|
||||
if (td.hasCode() && (tt.equals(t))) {
|
||||
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
|
||||
for (UriType u : ts.getTargetProfile()) {
|
||||
String url = u.getValue();
|
||||
boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url);
|
||||
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);
|
||||
}
|
||||
}
|
||||
boolean tgtOk = !td.hasTargetProfile() || sdConformsToTargets(path, derived.getPath(), url, td);
|
||||
if (tgtOk) {
|
||||
ok = true;
|
||||
} else {
|
||||
|
@ -2899,11 +2887,34 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
}
|
||||
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) {
|
||||
boolean ok = false;
|
||||
Set<String> types = new HashSet<>();
|
||||
|
|
|
@ -2587,7 +2587,7 @@ public boolean hasTarget() {
|
|||
res = res + "}";
|
||||
}
|
||||
if (hasTargetProfile()) {
|
||||
res = res + "->(";
|
||||
res = res + "(";
|
||||
boolean first = true;
|
||||
for (CanonicalType s : getTargetProfile()) {
|
||||
if (first) first = false; else res = res + "|";
|
||||
|
|
|
@ -647,6 +647,10 @@ public class Utilities {
|
|||
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 {
|
||||
String[] a = new String[args.length+1];
|
||||
a[0] = f.getAbsolutePath();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.hl7.fhir.utilities.json.parser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -167,6 +168,12 @@ public class JsonParser {
|
|||
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) {
|
||||
return composeBytes(element, false);
|
||||
}
|
||||
|
@ -179,6 +186,12 @@ public class JsonParser {
|
|||
byte[] cnt = composeBytes(element, pretty);
|
||||
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) {
|
||||
String s = compose(element, pretty);
|
||||
|
|
|
@ -5,7 +5,9 @@ import java.io.IOException;
|
|||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
|
@ -67,6 +69,10 @@ public class PackageList {
|
|||
json.set("date", date);
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return json.asString("name");
|
||||
}
|
||||
|
||||
public List<String> subPackages() {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (json.has("sub-packages")) {
|
||||
|
@ -169,6 +175,7 @@ public class PackageList {
|
|||
}
|
||||
setDate(date);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String source;
|
||||
|
@ -334,5 +341,15 @@ public class PackageList {
|
|||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue