various fixes for reported bugs (#252)
* fix bug in Definition mode - support ofType() * fix bug reading old packages * fix for invalid OperationOutome if nothing is wrong * more fix for when no errors found
This commit is contained in:
parent
c1f5244873
commit
0e8b5f6552
|
@ -4433,7 +4433,8 @@ public class FHIRPathEngine {
|
||||||
public ElementDefinition evaluateDefinition(ExpressionNode expr, StructureDefinition profile, ElementDefinition element) throws DefinitionException {
|
public ElementDefinition evaluateDefinition(ExpressionNode expr, StructureDefinition profile, ElementDefinition element) throws DefinitionException {
|
||||||
StructureDefinition sd = profile;
|
StructureDefinition sd = profile;
|
||||||
ElementDefinition focus = null;
|
ElementDefinition focus = null;
|
||||||
|
boolean okToNotResolve = false;
|
||||||
|
|
||||||
if (expr.getKind() == Kind.Name) {
|
if (expr.getKind() == Kind.Name) {
|
||||||
if (element.hasSlicing()) {
|
if (element.hasSlicing()) {
|
||||||
ElementDefinition slice = pickMandatorySlice(sd, element);
|
ElementDefinition slice = pickMandatorySlice(sd, element);
|
||||||
|
@ -4493,6 +4494,19 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if ("ofType".equals(expr.getName())) {
|
||||||
|
if (!element.hasType())
|
||||||
|
throw new DefinitionException("illegal use of ofType() in discriminator - no type on element "+element.getId());
|
||||||
|
if (element.getType().size() > 1)
|
||||||
|
throw new DefinitionException("illegal use of ofType() in discriminator - Multiple possible types on "+element.getId());
|
||||||
|
if (!element.getType().get(0).hasCode())
|
||||||
|
throw new DefinitionException("illegal use of ofType() in discriminator - Type has no code on "+element.getId());
|
||||||
|
String atn = element.getType().get(0).getCode();
|
||||||
|
String stn = expr.getParameters().get(0).getName();
|
||||||
|
okToNotResolve = true;
|
||||||
|
if ((atn.equals(stn))) {
|
||||||
|
focus = element;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
throw new DefinitionException("illegal function name "+expr.getName()+"() in discriminator");
|
throw new DefinitionException("illegal function name "+expr.getName()+"() in discriminator");
|
||||||
} else if (expr.getKind() == Kind.Group) {
|
} else if (expr.getKind() == Kind.Group) {
|
||||||
|
@ -4501,9 +4515,13 @@ public class FHIRPathEngine {
|
||||||
throw new DefinitionException("illegal expression syntax in discriminator (const)");
|
throw new DefinitionException("illegal expression syntax in discriminator (const)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (focus == null)
|
if (focus == null) {
|
||||||
throw new DefinitionException("Unable to resolve discriminator in definitions: "+expr.toString());
|
if (okToNotResolve) {
|
||||||
else if (expr.getInner() == null)
|
return null;
|
||||||
|
} else {
|
||||||
|
throw new DefinitionException("Unable to resolve discriminator in definitions: "+expr.toString());
|
||||||
|
}
|
||||||
|
} else if (expr.getInner() == null)
|
||||||
return focus;
|
return focus;
|
||||||
else {
|
else {
|
||||||
return evaluateDefinition(expr.getInner(), sd, focus);
|
return evaluateDefinition(expr.getInner(), sd, focus);
|
||||||
|
|
|
@ -120,7 +120,10 @@ public class NpmPackage {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readIndex(JsonObject index) {
|
public boolean readIndex(JsonObject index) {
|
||||||
|
if (!index.has("index-version") || (index.get("index-version").getAsInt() != 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
this.index = index;
|
this.index = index;
|
||||||
for (JsonElement e : index.getAsJsonArray("files")) {
|
for (JsonElement e : index.getAsJsonArray("files")) {
|
||||||
JsonObject file = (JsonObject) e;
|
JsonObject file = (JsonObject) e;
|
||||||
|
@ -130,6 +133,7 @@ public class NpmPackage {
|
||||||
types.put(type, new ArrayList<>());
|
types.put(type, new ArrayList<>());
|
||||||
types.get(type).add(name);
|
types.get(type).add(name);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> listFiles() {
|
public List<String> listFiles() {
|
||||||
|
@ -210,7 +214,7 @@ public class NpmPackage {
|
||||||
*/
|
*/
|
||||||
public static NpmPackage fromFolder(String path) throws IOException {
|
public static NpmPackage fromFolder(String path) throws IOException {
|
||||||
NpmPackage res = new NpmPackage();
|
NpmPackage res = new NpmPackage();
|
||||||
loadFiles(res, path, new File(path));
|
res.loadFiles(path, new File(path));
|
||||||
res.checkIndexed(path);
|
res.checkIndexed(path);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -228,9 +232,9 @@ public class NpmPackage {
|
||||||
return userData;
|
return userData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadFiles(NpmPackage res, String path, File source, String... exemptions) throws FileNotFoundException, IOException {
|
public void loadFiles(String path, File source, String... exemptions) throws FileNotFoundException, IOException {
|
||||||
res.npm = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.fileToString(Utilities.path(path, "package", "package.json")));
|
this.npm = (JsonObject) new com.google.gson.JsonParser().parse(TextFile.fileToString(Utilities.path(path, "package", "package.json")));
|
||||||
res.path = path;
|
this.path = path;
|
||||||
|
|
||||||
File dir = new File(path);
|
File dir = new File(path);
|
||||||
for (File f : dir.listFiles()) {
|
for (File f : dir.listFiles()) {
|
||||||
|
@ -240,22 +244,24 @@ public class NpmPackage {
|
||||||
if (!d.equals("package")) {
|
if (!d.equals("package")) {
|
||||||
d = Utilities.path("package", d);
|
d = Utilities.path("package", d);
|
||||||
}
|
}
|
||||||
NpmPackageFolder folder = res.new NpmPackageFolder(d);
|
NpmPackageFolder folder = this.new NpmPackageFolder(d);
|
||||||
folder.folder = f;
|
folder.folder = f;
|
||||||
res.folders.put(d, folder);
|
this.folders.put(d, folder);
|
||||||
File ij = new File(Utilities.path(f.getAbsolutePath(), ".index.json"));
|
File ij = new File(Utilities.path(f.getAbsolutePath(), ".index.json"));
|
||||||
if (ij.exists()) {
|
if (ij.exists()) {
|
||||||
try {
|
try {
|
||||||
folder.readIndex(JsonTrackingParser.parseJson(ij));
|
if (!folder.readIndex(JsonTrackingParser.parseJson(ij))) {
|
||||||
|
indexFolder(folder.getName(), folder);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Error parsing "+ij.getAbsolutePath()+": "+e.getMessage(), e);
|
throw new IOException("Error parsing "+ij.getAbsolutePath()+": "+e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadSubFolders(res, dir.getAbsolutePath(), f);
|
loadSubFolders(dir.getAbsolutePath(), f);
|
||||||
} else {
|
} else {
|
||||||
NpmPackageFolder folder = res.new NpmPackageFolder(Utilities.path("package", "$root"));
|
NpmPackageFolder folder = this.new NpmPackageFolder(Utilities.path("package", "$root"));
|
||||||
folder.folder = dir;
|
folder.folder = dir;
|
||||||
res.folders.put(Utilities.path("package", "$root"), folder);
|
this.folders.put(Utilities.path("package", "$root"), folder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,25 +271,27 @@ public class NpmPackage {
|
||||||
return Utilities.existsInList(f.getName(), ".git", ".svn") || Utilities.existsInList(f.getName(), "package-list.json");
|
return Utilities.existsInList(f.getName(), ".git", ".svn") || Utilities.existsInList(f.getName(), "package-list.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadSubFolders(NpmPackage res, String rootPath, File dir) throws IOException {
|
private void loadSubFolders(String rootPath, File dir) throws IOException {
|
||||||
for (File f : dir.listFiles()) {
|
for (File f : dir.listFiles()) {
|
||||||
if (f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
String d = f.getAbsolutePath().substring(rootPath.length()+1);
|
String d = f.getAbsolutePath().substring(rootPath.length()+1);
|
||||||
if (!d.startsWith("package")) {
|
if (!d.startsWith("package")) {
|
||||||
d = Utilities.path("package", d);
|
d = Utilities.path("package", d);
|
||||||
}
|
}
|
||||||
NpmPackageFolder folder = res.new NpmPackageFolder(d);
|
NpmPackageFolder folder = this.new NpmPackageFolder(d);
|
||||||
folder.folder = f;
|
folder.folder = f;
|
||||||
res.folders.put(d, folder);
|
this.folders.put(d, folder);
|
||||||
File ij = new File(Utilities.path(f.getAbsolutePath(), ".index.json"));
|
File ij = new File(Utilities.path(f.getAbsolutePath(), ".index.json"));
|
||||||
if (ij.exists()) {
|
if (ij.exists()) {
|
||||||
try {
|
try {
|
||||||
folder.readIndex(JsonTrackingParser.parseJson(ij));
|
if (!folder.readIndex(JsonTrackingParser.parseJson(ij))) {
|
||||||
|
indexFolder(folder.getName(), folder);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Error parsing "+ij.getAbsolutePath()+": "+e.getMessage(), e);
|
throw new IOException("Error parsing "+ij.getAbsolutePath()+": "+e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadSubFolders(res, rootPath, f);
|
loadSubFolders(rootPath, f);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,7 +299,7 @@ public class NpmPackage {
|
||||||
|
|
||||||
public static NpmPackage fromFolder(String folder, PackageType defType, String... exemptions) throws IOException {
|
public static NpmPackage fromFolder(String folder, PackageType defType, String... exemptions) throws IOException {
|
||||||
NpmPackage res = new NpmPackage();
|
NpmPackage res = new NpmPackage();
|
||||||
loadFiles(res, folder, new File(folder), exemptions);
|
res.loadFiles(folder, new File(folder), exemptions);
|
||||||
if (!res.folders.containsKey("package")) {
|
if (!res.folders.containsKey("package")) {
|
||||||
res.folders.put("package", res.new NpmPackageFolder("package"));
|
res.folders.put("package", res.new NpmPackageFolder("package"));
|
||||||
}
|
}
|
||||||
|
@ -386,29 +394,36 @@ public class NpmPackage {
|
||||||
|
|
||||||
private void checkIndexed(String desc) throws IOException {
|
private void checkIndexed(String desc) throws IOException {
|
||||||
for (NpmPackageFolder folder : folders.values()) {
|
for (NpmPackageFolder folder : folders.values()) {
|
||||||
List<String> remove = new ArrayList<>();
|
|
||||||
if (folder.index == null) {
|
if (folder.index == null) {
|
||||||
NpmPackageIndexBuilder indexer = new NpmPackageIndexBuilder();
|
indexFolder(desc, folder);
|
||||||
indexer.start();
|
|
||||||
for (String n : folder.listFiles()) {
|
|
||||||
if (!indexer.seeFile(n, folder.fetchFile(n))) {
|
|
||||||
remove.add(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String n : remove) {
|
|
||||||
folder.removeFile(n);
|
|
||||||
}
|
|
||||||
String json = indexer.build();
|
|
||||||
try {
|
|
||||||
folder.readIndex(JsonTrackingParser.parseJson(json));
|
|
||||||
} catch (Exception e) {
|
|
||||||
TextFile.stringToFile(json, Utilities.path("[tmp]", ".index.json"));
|
|
||||||
throw new IOException("Error parsing "+(desc == null ? "" : desc+"#")+"package/"+folder.name+"/.index.json: "+e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void indexFolder(String desc, NpmPackageFolder folder) throws FileNotFoundException, IOException {
|
||||||
|
List<String> remove = new ArrayList<>();
|
||||||
|
NpmPackageIndexBuilder indexer = new NpmPackageIndexBuilder();
|
||||||
|
indexer.start();
|
||||||
|
for (String n : folder.listFiles()) {
|
||||||
|
if (!indexer.seeFile(n, folder.fetchFile(n))) {
|
||||||
|
remove.add(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String n : remove) {
|
||||||
|
folder.removeFile(n);
|
||||||
|
}
|
||||||
|
String json = indexer.build();
|
||||||
|
try {
|
||||||
|
folder.readIndex(JsonTrackingParser.parseJson(json));
|
||||||
|
if (folder.folder != null) {
|
||||||
|
TextFile.stringToFile(json, Utilities.path(folder.folder.getAbsolutePath(), ".index.json"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
TextFile.stringToFile(json, Utilities.path("[tmp]", ".index.json"));
|
||||||
|
throw new IOException("Error parsing "+(desc == null ? "" : desc+"#")+"package/"+folder.name+"/.index.json: "+e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static NpmPackage fromZip(InputStream stream, boolean dropRootFolder, String desc) throws IOException {
|
public static NpmPackage fromZip(InputStream stream, boolean dropRootFolder, String desc) throws IOException {
|
||||||
NpmPackage res = new NpmPackage();
|
NpmPackage res = new NpmPackage();
|
||||||
|
|
|
@ -501,4 +501,5 @@ public class I18nConstants {
|
||||||
public static final String _HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_ = "_has_children__and_multiple_types__in_profile_";
|
public static final String _HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_ = "_has_children__and_multiple_types__in_profile_";
|
||||||
public static final String _HAS_CHILDREN__FOR_TYPE__IN_PROFILE__BUT_CANT_FIND_TYPE = "_has_children__for_type__in_profile__but_cant_find_type";
|
public static final String _HAS_CHILDREN__FOR_TYPE__IN_PROFILE__BUT_CANT_FIND_TYPE = "_has_children__for_type__in_profile__but_cant_find_type";
|
||||||
public static final String _HAS_NO_CHILDREN__AND_NO_TYPES_IN_PROFILE_ = "_has_no_children__and_no_types_in_profile_";
|
public static final String _HAS_NO_CHILDREN__AND_NO_TYPES_IN_PROFILE_ = "_has_no_children__and_no_types_in_profile_";
|
||||||
|
public static final String ALL_OK = "ALL_OK";
|
||||||
}
|
}
|
|
@ -502,3 +502,4 @@ VALIDATION_VAL_ILLEGAL_TYPE_CONSTRAINT = Illegal constraint in profile {0} at pa
|
||||||
EXTENSION_EXT_CONTEXT_WRONG_XVER = The extension {0} from FHIR version {3} is not allowed to be used at this point (allowed = {1}; this element is [{2}; this is a warning since contexts may be renamed between FHIR versions)
|
EXTENSION_EXT_CONTEXT_WRONG_XVER = The extension {0} from FHIR version {3} is not allowed to be used at this point (allowed = {1}; this element is [{2}; this is a warning since contexts may be renamed between FHIR versions)
|
||||||
SECURITY_STRING_CONTENT_ERROR = The string value contains embedded HTML tags, which are not allowed for security reasons in this context
|
SECURITY_STRING_CONTENT_ERROR = The string value contains embedded HTML tags, which are not allowed for security reasons in this context
|
||||||
SECURITY_STRING_CONTENT_WARNING = The string value contains embedded HTML tags. Note that all inputs should be escaped when rendered to HTML as a matter of course
|
SECURITY_STRING_CONTENT_WARNING = The string value contains embedded HTML tags. Note that all inputs should be escaped when rendered to HTML as a matter of course
|
||||||
|
ALL_OK = All OK
|
|
@ -40,6 +40,8 @@ import org.hl7.fhir.utilities.VersionUtilities;
|
||||||
import org.hl7.fhir.utilities.cache.NpmPackage;
|
import org.hl7.fhir.utilities.cache.NpmPackage;
|
||||||
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
|
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
|
||||||
import org.hl7.fhir.utilities.cache.ToolsVersion;
|
import org.hl7.fhir.utilities.cache.ToolsVersion;
|
||||||
|
import org.hl7.fhir.utilities.i18n.I18nBase;
|
||||||
|
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||||
|
@ -1191,6 +1193,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
||||||
}
|
}
|
||||||
op.getIssue().add(OperationOutcomeUtilities.convertToIssue(vm, op));
|
op.getIssue().add(OperationOutcomeUtilities.convertToIssue(vm, op));
|
||||||
}
|
}
|
||||||
|
if (!op.hasIssue()) {
|
||||||
|
op.addIssue().setSeverity(OperationOutcome.IssueSeverity.INFORMATION).setCode(OperationOutcome.IssueType.INFORMATIONAL).getDetails().setText(context.formatMessage(I18nConstants.ALL_OK));
|
||||||
|
}
|
||||||
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
|
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
|
||||||
RendererFactory.factory(op, rc).render(op);
|
RendererFactory.factory(op, rc).render(op);
|
||||||
return op;
|
return op;
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class ValidationEngineTests {
|
||||||
}
|
}
|
||||||
Assertions.assertEquals(0, e);
|
Assertions.assertEquals(0, e);
|
||||||
Assertions.assertEquals(0, w);
|
Assertions.assertEquals(0, w);
|
||||||
Assertions.assertEquals(0, h);
|
Assertions.assertEquals(1, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -52,7 +52,7 @@ public class ValidationEngineTests {
|
||||||
int h = hints(op);
|
int h = hints(op);
|
||||||
Assertions.assertEquals(0, e);
|
Assertions.assertEquals(0, e);
|
||||||
Assertions.assertEquals(0, w);
|
Assertions.assertEquals(0, w);
|
||||||
Assertions.assertEquals(0, h);
|
Assertions.assertEquals(1, h);
|
||||||
if (!TestUtilities.silent)
|
if (!TestUtilities.silent)
|
||||||
System.out.println(" .. done: " + Integer.toString(e) + " errors, " + Integer.toString(w) + " warnings, " + Integer.toString(h) + " information messages");
|
System.out.println(" .. done: " + Integer.toString(e) + " errors, " + Integer.toString(w) + " warnings, " + Integer.toString(h) + " information messages");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue