diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/filesystem/DirectoryVisitor.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/filesystem/DirectoryVisitor.java new file mode 100644 index 000000000..27b164098 --- /dev/null +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/filesystem/DirectoryVisitor.java @@ -0,0 +1,78 @@ +package org.hl7.fhir.utilities.filesystem; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import org.hl7.fhir.utilities.Utilities; + +public class DirectoryVisitor { + + public interface IDirectoryVisitorImplementation { + boolean enterDirectory(File directory) throws IOException; + boolean visitFile(File file) throws IOException; // return true if count + } + + private IDirectoryVisitorImplementation worker; + private Set extensions; + + public DirectoryVisitor(IDirectoryVisitorImplementation worker, Set extensions) { + super(); + this.worker = worker; + this.extensions = extensions; + if (this.extensions == null) { + extensions = new HashSet<>(); + } + } + + public DirectoryVisitor(IDirectoryVisitorImplementation worker, String... extensionList) { + super(); + this.worker = worker; + extensions = new HashSet<>(); + for (String s : extensionList) { + extensions.add(s); + } + } + + public DirectoryVisitor(IDirectoryVisitorImplementation worker) { + super(); + this.worker = worker; + extensions = new HashSet<>(); + } + + public static int visitDirectory(IDirectoryVisitorImplementation worker, String path) throws IOException { + return new DirectoryVisitor(worker).visit(path); + } + + public static int visitDirectory(IDirectoryVisitorImplementation worker, String path, Set extensions) throws IOException { + return new DirectoryVisitor(worker, extensions).visit(path); + } + + public static int visitDirectory(IDirectoryVisitorImplementation worker, String path, String... extensionList) throws IOException { + return new DirectoryVisitor(worker, extensionList).visit(path); + } + + public int visit(String path) throws IOException { + return visit(ManagedFileAccess.file(path)); + } + + private int visit(File file) throws IOException { + int count = 0; + if (file.isDirectory()) { + if (worker.enterDirectory(file)) { + for (File f : ManagedFileAccess.listFiles(file)) { + count += visit(f); + } + } + } else { + String ext = file.getName().substring(file.getName().lastIndexOf(".")+1); + if (extensions.isEmpty() || extensions.contains(ext)) { + if (worker.visitFile(file)) { + count++; + } + } + } + return count; + } +} diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/filesystem/ManagedFileAccess.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/filesystem/ManagedFileAccess.java index 2e261b9fd..0a5caae35 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/filesystem/ManagedFileAccess.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/filesystem/ManagedFileAccess.java @@ -61,6 +61,7 @@ public class ManagedFileAccess { FileInputStream inStream(String pathname); FileOutputStream outStream(String pathname); CSFile csfile(String pathname); + File[] listFiles(File file) throws IOException; // file would be returned from file() above } public enum FileAccessPolicy { @@ -222,4 +223,20 @@ public class ManagedFileAccess { } } + public static File[] listFiles(File f) throws IOException { + switch (accessPolicy) { + case DIRECT: + if (!inAllowedPaths(f.getAbsolutePath())) { + throw new IOException("The pathname '"+f.getAbsolutePath()+"' cannot be accessed by policy"); + } + return f.listFiles(); + case MANAGED: + return accessor.listFiles(f); + case PROHIBITED: + throw new IOException("Access to files is not allowed by local security policy"); + default: + throw new IOException("Internal Error"); + } + } + } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java index c6746d1b4..2605b5627 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java @@ -1079,4 +1079,5 @@ public class I18nConstants { public static final String SD_TYPE_PARAMETER_INVALID = "SD_TYPE_PARAMETER_INVALID"; public static final String SD_TYPE_PARAMETER_INVALID_REF = "SD_TYPE_PARAMETER_INVALID_REF"; public static final String SD_TYPE_PARAM_NOT_SPECIFIED = "SD_TYPE_PARAM_NOT_SPECIFIED"; + public static final String SD_TYPE_PARAMETER_ABSTRACT_WARNING = "SD_TYPE_PARAMETER_ABSTRACT_WARNING"; } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/POGenerator.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/POGenerator.java index ac736d0c2..8a5fb35d0 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/POGenerator.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/POGenerator.java @@ -16,6 +16,8 @@ import java.util.Set; import org.hl7.fhir.utilities.StringPair; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.filesystem.DirectoryVisitor; +import org.hl7.fhir.utilities.filesystem.DirectoryVisitor.IDirectoryVisitorImplementation; import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; /** @@ -123,9 +125,9 @@ public class POGenerator { } cd.defined = found; } - scanJavaSource(new File(core), consts, "RenderingI18nContext", "RenderingContext"); - scanJavaSource(new File(igpub), consts, "RenderingI18nContext", "RenderingContext"); - scanPascalSource(new File(pascal), props); + scanJavaSource(core, consts, "RenderingI18nContext", "RenderingContext"); + scanJavaSource(igpub, consts, "RenderingI18nContext", "RenderingContext"); + scanPascalSource(pascal, props); Set pns = new HashSet<>(); for (PropertyValue p : props) { @@ -170,9 +172,9 @@ public class POGenerator { cd.defined = found; } - scanJavaSource(new File(core), consts, "I18nConstants"); - scanJavaSource(new File(igpub), consts, "I18nConstants"); - scanPascalSource(new File(pascal), props); + scanJavaSource(core, consts, "I18nConstants"); + scanJavaSource(igpub, consts, "I18nConstants"); + scanPascalSource(pascal, props); pns = new HashSet<>(); for (PropertyValue p : props) { @@ -212,73 +214,86 @@ public class POGenerator { return ok; } - private boolean scanJavaSource(File file, List consts, String... names) throws FileNotFoundException, IOException { - if (file.isDirectory()) { - boolean found = true; - for (File f : file.listFiles()) { - if (!Utilities.existsInList(f.getName(), "model", "formats")) { - found = scanJavaSource(f, consts, names) && found; - } - } - return false; - } else { - String ext = file.getName().substring(file.getName().lastIndexOf(".")+1); - if ("java".equals(ext)) { - String source = TextFile.fileToString(file); - for (ConstantDefinition cd : consts) { - if (!cd.used) { - boolean found = false; - for (String n : names) { - if (source.contains(n+"."+cd.name+",")) { - found = true; - } - if (source.contains(n+"."+cd.name+")")) { - found = true; - } - if (source.contains(n+"."+cd.name+" :")) { - found = true; - } - if (source.contains(n+"."+cd.name+";")) { - found = true; - } - } - if (found) { - cd.used = true; - } - } - } - return true; - } else { - return false; - } + private class JavaScanner implements IDirectoryVisitorImplementation { + List consts; + List names; + + @Override + public boolean enterDirectory(File f) throws IOException { + return !Utilities.existsInList(f.getName(), "model", "formats"); } - } - - private void scanPascalSource(File file, List defs) throws FileNotFoundException, IOException { - if (file.isDirectory()) { - for (File f : file.listFiles()) { - scanPascalSource(f, defs); - } - } else { - String ext = file.getName().substring(file.getName().lastIndexOf(".")+1); - if ("pas".equals(ext)) { - String source = TextFile.fileToString(file); - for (PropertyValue pv : defs) { - if (!pv.used) { - boolean found = false; - String pn = pv.getBaseName(); - if (source.contains("'"+pn+"'")) { + @Override + public boolean visitFile(File file) throws IOException { + String source = TextFile.fileToString(file); + for (ConstantDefinition cd : consts) { + if (!cd.used) { + boolean found = false; + for (String n : names) { + if (source.contains(n+"."+cd.name+",")) { found = true; } - if (found) { - pv.used = true; - } + if (source.contains(n+"."+cd.name+")")) { + found = true; + } + if (source.contains(n+"."+cd.name+" :")) { + found = true; + } + if (source.contains(n+"."+cd.name+";")) { + found = true; + } + } + if (found) { + cd.used = true; + } + } + } + return true; + } + } + + private void scanJavaSource(String path, List consts, String... names) throws FileNotFoundException, IOException { + JavaScanner scanner = new JavaScanner(); + scanner.consts = consts; + scanner.names = new ArrayList(); + for (String s : names) { + scanner.names.add(s); + } + DirectoryVisitor.visitDirectory(scanner, path, "java"); + } + + private class PascalScanner implements IDirectoryVisitorImplementation { + private List defs; + + @Override + public boolean enterDirectory(File directory) throws IOException { + return true; + } + + @Override + public boolean visitFile(File file) throws IOException { + String source = TextFile.fileToString(file); + for (PropertyValue pv : defs) { + if (!pv.used) { + boolean found = false; + String pn = pv.getBaseName(); + if (source.contains("'"+pn+"'")) { + found = true; + } + if (found) { + pv.used = true; } } } + return true; } } + + private void scanPascalSource(String path, List defs) throws FileNotFoundException, IOException { + PascalScanner scanner = new PascalScanner(); + scanner.defs = defs; + DirectoryVisitor.visitDirectory(scanner, path, "pas"); + } private List loadConstants(String path) throws FileNotFoundException, IOException { @@ -438,7 +453,7 @@ public class POGenerator { } } } else { - // we don't care; nothing to do + o.oldMsgId = null; } } else if (mode == 1) { if (!value.equals(o.msgid)) { @@ -451,7 +466,7 @@ public class POGenerator { o.msgstr.set(0, "!!"+o.msgstr.get(0)); } } else { - // we don't care; nothing to do + o.oldMsgId = null; } } else if (mode == 2) { if (!value.equals(o.msgidPlural)) { @@ -464,7 +479,7 @@ public class POGenerator { o.msgstr.set(1, "!!"+o.msgstr.get(1)); } } else { - // we don't care; nothing to do + o.oldMsgId = null; } } } diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index d8e5462c1..527bc80b7 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -20,7 +20,7 @@ BUNDLE_BUNDLE_ENTRY_FOUND_MULTIPLE_FRAGMENT = Found {0} matches for fragment {2} BUNDLE_BUNDLE_ENTRY_FULLURL_REQUIRED = Except for transactions and batches, each entry in a Bundle must have a fullUrl which is the identity of the resource in the entry BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES_MULTIPLE_MATCHES = The {1} resource matched more than one of the allowed profiles ({3}) BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES_NO_MATCH = The {1} resource did not match any of the allowed profiles (Type {2}: {3}) -BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES_NO_MATCH_REASON = The {1} resource did not math the profile {2} because: {3} +BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES_NO_MATCH_REASON = The {1} resource did not match the profile {2} because: {3} BUNDLE_BUNDLE_ENTRY_NOTFOUND_APPARENT_one = Can''t find ''{1}'' in the bundle ({2}). Note that there is a resource in the bundle with the same type and id, but it does not match because of the fullUrl based rules around matching relative references (must be ``{3}``) BUNDLE_BUNDLE_ENTRY_NOTFOUND_APPARENT_other = Can''t find ''{1}'' in the bundle ({2}). Note that there are {0} resources in the bundle with the same type and id, but they do not match because of the fullUrl based rules around matching relative references (one of ``{3}``) BUNDLE_BUNDLE_ENTRY_NOTFOUND_FRAGMENT = Can''t find ''{0}'' in the bundle ({1}) @@ -1107,3 +1107,4 @@ SD_TYPE_PARAMETER_UNKNOWN = The type definition ''{0}'' has the type parameter ' SD_TYPE_PARAMETER_INVALID = The type definition ''{2}'' has a type parameter ''{3}'', which is not consistent with it''s ancestor type definition ''{0}'' which has the type parameter ''{1}'' SD_TYPE_PARAMETER_INVALID_REF = The type ''{0}'' is a reference to ''{1}'' which has a type parameter ''{2}'' with a base type of {3} but the type parameter provided is ''{4}'' which is not the right type SD_TYPE_PARAM_NOT_SPECIFIED = The type ''{0}'' at {3} is a reference to ''{1}'' which needs a type parameter ''{2}'' but a type parameter is not provided for ''{2}'' +SD_TYPE_PARAMETER_ABSTRACT_WARNING = The type ''{0}'' at {3} refers to the abstract type ''{1}'' but the context is not an abstract type - this is usually an error diff --git a/org.hl7.fhir.utilities/src/main/resources/rendering-phrases.properties b/org.hl7.fhir.utilities/src/main/resources/rendering-phrases.properties index d6c6e023d..4d957579f 100644 --- a/org.hl7.fhir.utilities/src/main/resources/rendering-phrases.properties +++ b/org.hl7.fhir.utilities/src/main/resources/rendering-phrases.properties @@ -132,7 +132,7 @@ CAPABILITY_TYPS = Types CAPABILITY_TYP_PRES = ype are only present if at least one of the resources has support for them. CAPABILITY_UPDATE_INT = PUT a new resource version (update interaction) CAPABILITY_VREAD_INT = GET past versions of resources (vread interaction) -CAPABILTY_ALLOW_CAP = Any FHIR capability may be 'allowed' by the system unless explicitly marked as 'SHALL NOT'. A few items are marked as MAY in the Implementation Guide to highlight their potential relevance to the use case. +CAPABILTY_ALLOW_CAP = Any FHIR capability may be ''allowed'' by the system unless explicitly marked as ''SHALL NOT''. A few items are marked as MAY in the Implementation Guide to highlight their potential relevance to the use case. CAPABILTY_SHALL_SUPP = SHALL Support the Following Implementation Guides CODESYSTEM_CONCEPTS = Concepts CODESYSTEM_CONTENT_COMPLETE = This code system defines the following codes: @@ -537,10 +537,10 @@ GENERAL_MODIFIERS = Modifiers SEARCH_PAR_MULTIPLES = Multiples SEARCH_PAR_MULTIPLE_AND_APPEAR = multipleAnd: The parameter may only appear once SEARCH_PAR_MULTIPLE_AND_REPEAT = multipleAnd: The parameter may repeat in order to specify multiple values that must all be true -SEARCH_PAR_MULTIPLE_AND_SERVER = multipleAnd: It's up to the server whether the parameter may repeat in order to specify multiple values that must all be true +SEARCH_PAR_MULTIPLE_AND_SERVER = multipleAnd: It''s up to the server whether the parameter may repeat in order to specify multiple values that must all be true SEARCH_PAR_MULTIPLE_OR_MULTIPLE = multipleOr: The parameter may have multiple values (separated by comma) where at least one must be true SEARCH_PAR_MULTIPLE_OR_ONE = multipleOr: The parameter may only have one value (no comma separators) -SEARCH_PAR_MULTIPLE_OR_SERVER = multipleOr: It's up to the server whether the parameter can have multiple values (separated by comma) where at least one must be true +SEARCH_PAR_MULTIPLE_OR_SERVER = multipleOr: It''s up to the server whether the parameter can have multiple values (separated by comma) where at least one must be true SEARCH_PAR_NONE = (none) SEARCH_PAR_PROC = Processing Mode SEARCH_PAR_REND_TARGET = Target Resources