From 236ed5273568a3c041f7c020675cbbdf1d623f0c Mon Sep 17 00:00:00 2001 From: sebg-mio42 Date: Fri, 6 Dec 2024 15:24:15 +0100 Subject: [PATCH 1/5] fix handling of versioned references in validator bundle entry resolution --- .../java/org/hl7/fhir/validation/BaseValidator.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java index c66e6e812..ea64621dc 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java @@ -168,6 +168,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi protected final String TYPE = "type"; protected final String BUNDLE = "Bundle"; protected final String LAST_UPDATED = "lastUpdated"; + protected final String VERSION_ID = "versionId"; protected BaseValidator parent; protected IWorkerContext context; @@ -1054,6 +1055,16 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi if (list == null) { list = new ArrayList(); relMap.put(rl, list); + boolean versionIdPresent = resource.hasChild(META, false) + && resource.getNamedChild(META, false).hasChild(VERSION_ID, false) + && resource.getNamedChild(META, false).getNamedChild(VERSION_ID, false).hasValue(); + if (versionIdPresent){ + String versionId = resource.getNamedChild(META).getNamedChild(VERSION_ID).getValue(); + String fullUrlVersioned = fu + "/_history/" + versionId; + String relativePathVersioned = rl + "/_history/" + versionId; + relMap.put(relativePathVersioned, list); + map.put(fullUrlVersioned, list); + } } list.add(entry); } From 5c1fac1a055aaa4a8dd5320de9ae7d1750842d32 Mon Sep 17 00:00:00 2001 From: sebg-mio42 Date: Fri, 6 Dec 2024 16:55:46 +0100 Subject: [PATCH 2/5] fix errors caused by using the same list for versioned and unversioned entries --- .../hl7/fhir/validation/BaseValidator.java | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java index ea64621dc..5e76f9a56 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java @@ -1049,25 +1049,40 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi if (resource != null) { String et = resource.getType(); String eid = resource.getNamedChildValue(ID, false); + String rl = null; if (eid != null) { - String rl = et+"/"+eid; + rl = et+"/"+eid; list = relMap.get(rl); if (list == null) { list = new ArrayList(); relMap.put(rl, list); - boolean versionIdPresent = resource.hasChild(META, false) - && resource.getNamedChild(META, false).hasChild(VERSION_ID, false) - && resource.getNamedChild(META, false).getNamedChild(VERSION_ID, false).hasValue(); - if (versionIdPresent){ - String versionId = resource.getNamedChild(META).getNamedChild(VERSION_ID).getValue(); - String fullUrlVersioned = fu + "/_history/" + versionId; - String relativePathVersioned = rl + "/_history/" + versionId; - relMap.put(relativePathVersioned, list); - map.put(fullUrlVersioned, list); - } } list.add(entry); } + boolean versionIdPresent = resource.hasChild(META, false) + && resource.getNamedChild(META, false).hasChild(VERSION_ID, false) + && resource.getNamedChild(META, false).getNamedChild(VERSION_ID, false).hasValue(); + if (versionIdPresent){ + String versionId = resource.getNamedChild(META).getNamedChild(VERSION_ID).getValue(); + String fullUrlVersioned = fu + "/_history/" + versionId; + List listMapVersioned = null; + listMapVersioned = map.get(fullUrlVersioned); + if (listMapVersioned == null) { + listMapVersioned = new ArrayList(); + map.put(fullUrlVersioned, listMapVersioned); + } + listMapVersioned.add(entry); + if (rl != null) { + String relativePathVersioned = rl + "/_history/" + versionId; + List listRelMapVersioned = null; + listRelMapVersioned = relMap.get(relativePathVersioned); + if (listRelMapVersioned == null) { + listRelMapVersioned = new ArrayList(); + relMap.put(relativePathVersioned, listRelMapVersioned); + } + listRelMapVersioned.add(entry); + } + } } } } From aef45e0ffa74c98e20ba50340bf1487398ce6d45 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Wed, 11 Dec 2024 04:38:15 +1100 Subject: [PATCH 3/5] remove dead code --- .../hl7/fhir/r4/utils/IntegrityChecker.java | 271 ------------------ .../hl7/fhir/utilities/SimpleTimeTracker.java | 90 ------ 2 files changed, 361 deletions(-) delete mode 100644 org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/IntegrityChecker.java delete mode 100644 org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SimpleTimeTracker.java diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/IntegrityChecker.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/IntegrityChecker.java deleted file mode 100644 index 3b3febc76..000000000 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/IntegrityChecker.java +++ /dev/null @@ -1,271 +0,0 @@ -package org.hl7.fhir.r4.utils; - -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r4.formats.JsonParser; -import org.hl7.fhir.r4.model.CodeType; -import org.hl7.fhir.r4.model.ElementDefinition; -import org.hl7.fhir.r4.model.SearchParameter; -import org.hl7.fhir.r4.model.StructureDefinition; -import org.hl7.fhir.r4.model.StructureDefinition.TypeDerivationRule; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.npm.NpmPackage; - -public class IntegrityChecker { - - public class SearchParameterNodeSorter implements Comparator { - - @Override - public int compare(SearchParameterNode o1, SearchParameterNode o2) { - return o1.name.compareTo(o2.name); - } - - } - - public class SearchParameterParamNodeSorter implements Comparator { - - @Override - public int compare(SearchParameterParamNode o1, SearchParameterParamNode o2) { - return o1.sp.getCode().compareTo(o2.sp.getCode()); - } - - } - - public class SearchParameterParamNode { - SearchParameter sp; - boolean only; - - public SearchParameterParamNode(SearchParameter sp, boolean only) { - super(); - this.sp = sp; - this.only = only; - } - - } - - public class SearchParameterNode { - - private String name; - private List params = new ArrayList<>(); - - public SearchParameterNode(String name) { - this.name = name; - } - - } - - public class StructureDefinitionNodeComparer implements Comparator { - - @Override - public int compare(StructureDefinitionNode arg0, StructureDefinitionNode arg1) { - if (arg0.sd.getType().equals(arg1.sd.getType())) { - return arg0.sd.getName().compareTo(arg1.sd.getName()); - } else { - return arg0.sd.getType().compareTo(arg1.sd.getType()); - } - } - - } - - public class StructureDefinitionNode { - StructureDefinition sd; - List children = new ArrayList<>(); - - public StructureDefinitionNode(StructureDefinition sd) { - this.sd = sd; - } - - } - - private NpmPackage npm; - - public static void main(String[] args) throws Exception { - IntegrityChecker check = new IntegrityChecker(); - check.load(args[0]); - check.check(); - } - - private void check() throws IOException { - dumpSD(new FileWriter("/Users/grahamegrieve/temp/r4-dump.txt")); -// checkSD(); -// checkSP(); - } - - private void dumpSD(FileWriter w) throws FHIRFormatError, IOException { - Map map = new HashMap<>(); - for (String sdn : npm.listResources("StructureDefinition")) { - InputStream s = npm.load(sdn); - StructureDefinition sd = (StructureDefinition) new JsonParser().parse(s); - map.put(sd.getUrl(), sd); - } - msg("Loaded " + map.size() + " Structures"); - List structures = new ArrayList<>(); - for (StructureDefinition sd : map.values()) { - structures.add(sd.getUrl()); - } - Collections.sort(structures); - - for (String sdn : structures) { - dumpSD(map.get(sdn), map, w); - } - } - - private void dumpSD(StructureDefinition sd, Map map, FileWriter w) throws IOException { - if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) { - StructureDefinition base = sd.hasBaseDefinition() ? map.get(sd.getBaseDefinition()) : null; - System.out.println(sd.getType() + (base == null ? "" : " : " + base.getType())); - w.append(sd.getType() + (base == null ? "" : " : " + base.getType()) + "\r\n"); - for (ElementDefinition ed : sd.getSnapshot().getElement()) { - w.append(" " + Utilities.padLeft("", ' ', Utilities.charCount(ed.getPath(), '.')) + tail(ed.getPath()) + " : " - + ed.typeSummary() + " [" + ed.getMin() + ".." + ed.getMax() + "]" + "\r\n"); - } - } - } - - private String tail(String path) { - return path.contains(".") ? path.substring(path.lastIndexOf('.') + 1) : path; - } - - private void checkSP() throws IOException { - List list = new ArrayList<>(); - for (String sdn : npm.listResources("SearchParameter")) { - InputStream s = npm.load(sdn); - SearchParameter sp = (SearchParameter) new JsonParser().parse(s); - list.add(sp); - } - msg("Loaded " + list.size() + " resources"); - Map map = new HashMap<>(); - for (SearchParameter sp : list) { - for (CodeType c : sp.getBase()) { - String s = c.primitiveValue(); - if (!map.containsKey(s)) { - map.put(s, new SearchParameterNode(s)); - } - addNode(sp, sp.getBase().size() == 1, map.get(s)); - } - } - for (SearchParameterNode node : sort(map.values())) { - dump(node); - } - } - - private void dump(SearchParameterNode node) { - msg(node.name); - for (SearchParameterParamNode p : sortP(node.params)) { - String exp = p.sp.getExperimental() ? " **exp!" : ""; - if (p.only) { - msg(" " + p.sp.getCode() + exp); - } else { - msg(" *" + p.sp.getCode() + exp); - } - } - - } - - private List sortP(List params) { - List res = new ArrayList<>(); - res.addAll(params); - Collections.sort(res, new SearchParameterParamNodeSorter()); - return res; - } - - private List sort(Collection values) { - List res = new ArrayList<>(); - res.addAll(values); - Collections.sort(res, new SearchParameterNodeSorter()); - return res; - } - - private void addNode(SearchParameter sp, boolean b, SearchParameterNode node) { - node.params.add(new SearchParameterParamNode(sp, b)); - } - - private void checkSD() throws IOException { - Map map = new HashMap<>(); - for (String sdn : npm.listResources("StructureDefinition")) { - InputStream s = npm.load(sdn); - StructureDefinition sd = (StructureDefinition) new JsonParser().parse(s); - map.put(sd.getUrl(), sd); - } - msg("Loaded " + map.size() + " resources"); - List roots = new ArrayList<>(); - for (StructureDefinition sd : map.values()) { - if (sd.getBaseDefinition() == null || !map.containsKey(sd.getBaseDefinition())) { - StructureDefinitionNode root = new StructureDefinitionNode(sd); - roots.add(root); - analyse(root, map); - } - } - sort(roots); - for (StructureDefinitionNode root : roots) { - describe(root, 0); - } - } - - private void sort(List list) { - Collections.sort(list, new StructureDefinitionNodeComparer()); - - } - - private void analyse(StructureDefinitionNode node, Map map) { - for (StructureDefinition sd : map.values()) { - if (node.sd.getUrl().equals(sd.getBaseDefinition())) { - StructureDefinitionNode c = new StructureDefinitionNode(sd); - node.children.add(c); - analyse(c, map); - } - } - sort(node.children); - } - - private void describe(StructureDefinitionNode node, int level) { - describe(node.sd, level); - for (StructureDefinitionNode c : node.children) { - describe(c, level + 1); - } - } - - private void describe(StructureDefinition sd, int level) { - String exp = sd.getExperimental() ? " **exp!" : ""; - if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) { - msg(Utilities.padLeft("", ' ', level) + sd.getType() + " / " + sd.getName() + " (" + sd.getUrl() + ")" + exp); - } else { - msg(Utilities.padLeft("", ' ', level) + sd.getType() + " : " + sd.getKind() + exp); - } - } - -// private int analyse(Map map, List list, StructureDefinition sd) { -// if (!list.contains(sd)) { -// int level = 0; -// if (sd.hasBaseDefinition()) { -// StructureDefinition p = map.get(sd.getBaseDefinition()); -// if (p == null) { -// msg("Can't find parent "+sd.getBaseDefinition()+" for "+sd.getUrl()); -// } else { -// level = analyse(map, list, p) + 1; -// } -// } -// list.add(sd); -// sd.setUserData("level", level); -// } -// } - - private void msg(String string) { - System.out.println(string); - } - - private void load(String folder) throws IOException { - msg("Loading resources from " + folder); - npm = NpmPackage.fromFolder(folder); - } -} diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SimpleTimeTracker.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SimpleTimeTracker.java deleted file mode 100644 index bbe9c2adf..000000000 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/SimpleTimeTracker.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.hl7.fhir.utilities; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; - -import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; - -public class SimpleTimeTracker { - - private long start; - private String name; - private String context; - private int count; - - public static int level = 0; - public static BufferedWriter bw; - - public SimpleTimeTracker(String name) { - level++; - this.name = name; - count = -1; - start = System.currentTimeMillis(); - init(); - log(name); - } - - public SimpleTimeTracker(String name, String context) { - level++; - this.name = name; - this.context = context; - start = System.currentTimeMillis(); - count = -1; - init(); - log(name+" ["+context+"]"); - } - - private void init() { - if (bw == null) { - try { - File fout = ManagedFileAccess.file("/Users/grahamegrieve/temp/time.txt"); - FileOutputStream fos = ManagedFileAccess.outStream(fout); - bw = new BufferedWriter(new OutputStreamWriter(fos)); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - } - - public void report() { - String s = count == -1 ? "" : " ("+count+")"; - if (context == null) { - s = name+": "+(System.currentTimeMillis()-start)+"ms "+s; - } else { - s = name+": "+(System.currentTimeMillis()-start)+"ms "+s+" ["+context+"]"; - } - log(s); - level--; - if (level == 0) { - try { - bw.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - private void log(String s) { - System.out.println(Utilities.padLeft("", '#', level)+" "+s); - try { - bw.write(s); - bw.newLine(); - } catch (Exception e) { - System.out.println("e: " +e.getMessage()); - } - } - - public void count() { - if (count == -1) { - count = 1; - } else { - count++; - } - - } - -} From fec504a0247b3f4cdd83e16f92dd322f8a1a729c Mon Sep 17 00:00:00 2001 From: dotasek Date: Wed, 11 Dec 2024 13:54:49 -0500 Subject: [PATCH 4/5] Update owasp plugin to 11.1.1 --- .github/workflows/owasp.yml | 10 ++++++++-- pom.xml | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/owasp.yml b/.github/workflows/owasp.yml index 238b77a4a..8625e3162 100644 --- a/.github/workflows/owasp.yml +++ b/.github/workflows/owasp.yml @@ -17,10 +17,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - run: | + - env: + NVD_API_KEY: + ${{ secrets.NVD_API_KEY }} + run: | mvn -DskipTests install -P OWASP_CHECK - - run: | + - env: + NVD_API_KEY: + ${{ secrets.NVD_API_KEY }} + run: | mvn -DskipTests dependency-check:aggregate -P OWASP_CHECK - name: Upload SARIF file diff --git a/pom.xml b/pom.xml index 0af1a743c..8de072975 100644 --- a/pom.xml +++ b/pom.xml @@ -384,8 +384,9 @@ org.owasp dependency-check-maven - 8.2.1 + 11.1.1 + NVD_API_KEY cve-suppression.xml From 2d2ebda065c248552326b349577dfa313546ee61 Mon Sep 17 00:00:00 2001 From: Lloyd McKenzie Date: Wed, 11 Dec 2024 21:43:31 -0700 Subject: [PATCH 5/5] Check for both "value" and "value[x]" --- .../convertors/conv40_50/resources40_50/ValueSet40_50.java | 7 +++++-- .../convertors/conv43_50/resources43_50/ValueSet43_50.java | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/ValueSet40_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/ValueSet40_50.java index 2fc2ae029..15e0ae211 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/ValueSet40_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv40_50/resources40_50/ValueSet40_50.java @@ -479,8 +479,11 @@ public class ValueSet40_50 { ConceptPropertyComponent prop = tgt.addProperty(); ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(t, prop, "code", "value[x]"); prop.setCode(t.getExtensionString("code")); - prop.setValue(ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().convertType(t.getExtensionByUrl("value[x]").getValue())); - + if (t.hasExtension("value")) { + prop.setValue(ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().convertType(t.getExtensionByUrl("value").getValue())); + } else if (t.hasExtension("value[x]")) { + prop.setValue(ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().convertType(t.getExtensionByUrl("value[x]").getValue())); + } } } for (org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent t : src.getContains()) diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv43_50/resources43_50/ValueSet43_50.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv43_50/resources43_50/ValueSet43_50.java index 91fc1f09e..a4ca500d3 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv43_50/resources43_50/ValueSet43_50.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/conv43_50/resources43_50/ValueSet43_50.java @@ -478,8 +478,11 @@ public class ValueSet43_50 { ValueSet.ConceptPropertyComponent prop = tgt.addProperty(); ConversionContext43_50.INSTANCE.getVersionConvertor_43_50().copyElement(t, prop, "code", "value[x]"); prop.setCode(t.getExtensionString("code")); - prop.setValue(ConversionContext43_50.INSTANCE.getVersionConvertor_43_50().convertType(t.getExtensionByUrl("value[x]").getValue())); - + if (t.hasExtension("value")) { + prop.setValue(ConversionContext43_50.INSTANCE.getVersionConvertor_43_50().convertType(t.getExtensionByUrl("value").getValue())); + } else if (t.hasExtension("value[x]")) { + prop.setValue(ConversionContext43_50.INSTANCE.getVersionConvertor_43_50().convertType(t.getExtensionByUrl("value[x]").getValue())); + } } } for (org.hl7.fhir.r4b.model.ValueSet.ValueSetExpansionContainsComponent t : src.getContains())