Skip to content

Commit

Permalink
Merge pull request #2904 from IBM/issue-2832
Browse files Browse the repository at this point in the history
Issue #2832 - enable default profile version configuration
  • Loading branch information
prb112 authored Oct 28, 2021
2 parents 31aac1b + 59ac8d4 commit 6f8c4da
Show file tree
Hide file tree
Showing 6 changed files with 343 additions and 79 deletions.
70 changes: 54 additions & 16 deletions docs/src/pages/guides/FHIRServerUsersGuide.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class FHIRConfiguration {
public static final String PROPERTY_FIELD_RESOURCES_PROFILES_AT_LEAST_ONE = "atLeastOne";
public static final String PROPERTY_FIELD_RESOURCES_PROFILES_NOT_ALLOWED = "notAllowed";
public static final String PROPERTY_FIELD_RESOURCES_PROFILES_ALLOW_UNKNOWN = "allowUnknown";
public static final String PROPERTY_FIELD_RESOURCES_PROFILES_DEFAULT_VERSIONS = "defaultVersions";

// Auth and security properties
public static final String PROPERTY_SECURITY_CORS = "fhirServer/security/cors";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.ibm.fhir.config.FHIRConfiguration;
import com.ibm.fhir.config.FHIRRequestContext;
import com.ibm.fhir.config.PropertyGroup;
import com.ibm.fhir.config.PropertyGroup.PropertyEntry;
import com.ibm.fhir.core.FHIRConstants;
import com.ibm.fhir.core.HTTPHandlingPreference;
import com.ibm.fhir.core.context.FHIRPagingContext;
Expand All @@ -61,11 +62,13 @@
import com.ibm.fhir.model.resource.Resource;
import com.ibm.fhir.model.resource.SearchParameter;
import com.ibm.fhir.model.resource.StructureDefinition;
import com.ibm.fhir.model.type.Canonical;
import com.ibm.fhir.model.type.Code;
import com.ibm.fhir.model.type.CodeableConcept;
import com.ibm.fhir.model.type.DateTime;
import com.ibm.fhir.model.type.Decimal;
import com.ibm.fhir.model.type.Extension;
import com.ibm.fhir.model.type.Meta;
import com.ibm.fhir.model.type.Reference;
import com.ibm.fhir.model.type.UnsignedInt;
import com.ibm.fhir.model.type.Uri;
Expand Down Expand Up @@ -2577,6 +2580,9 @@ private List<Issue> validateResource(Resource resource) throws FHIRValidationExc
Set<String> notAllowedProfiles = new HashSet<>();
Set<String> notAllowedProfilesWithoutVersion = new HashSet<>();
boolean allowUnknown;
Map<String, String> defaultVersions = new HashMap<>();
boolean defaultVersionsSpecified = false;
Resource resourceToValidate = resource;

// Retrieve the profile configuration
try {
Expand Down Expand Up @@ -2648,40 +2654,84 @@ private List<Issue> validateResource(Resource resource) throws FHIRValidationExc
allowUnknown = FHIRConfigHelper.getBooleanProperty(defaultProfileConfigPath.toString() +
FHIRConfiguration.PROPERTY_FIELD_RESOURCES_PROFILES_ALLOW_UNKNOWN, Boolean.TRUE);
}

if (log.isLoggable(Level.FINER)) {
log.finer("Allow unknown: " + allowUnknown);
}

// Get the 'defaultVersions' entries
PropertyGroup resourceSpecificDefaultVersionsGroup =
FHIRConfigHelper.getPropertyGroup(resourceSpecificProfileConfigPath.toString() +
FHIRConfiguration.PROPERTY_FIELD_RESOURCES_PROFILES_DEFAULT_VERSIONS);
if (resourceSpecificDefaultVersionsGroup != null) {
defaultVersionsSpecified = true;
for (PropertyEntry entry : resourceSpecificDefaultVersionsGroup.getProperties()) {
defaultVersions.put(entry.getName(), (String) entry.getValue());
}
} else {
PropertyGroup allResourceDefaultVersionsGroup =
FHIRConfigHelper.getPropertyGroup(defaultProfileConfigPath.toString() +
FHIRConfiguration.PROPERTY_FIELD_RESOURCES_PROFILES_DEFAULT_VERSIONS);
if (allResourceDefaultVersionsGroup != null) {
defaultVersionsSpecified = true;
for (PropertyEntry entry : allResourceDefaultVersionsGroup.getProperties()) {
defaultVersions.put(entry.getName(), (String) entry.getValue());
}
}
}

if (log.isLoggable(Level.FINER)) {
log.finer("Default profile versions: [");
for (String profile : defaultVersions.keySet()) {
log.finer(" " + profile + " : " + defaultVersions.get(profile));
}
log.finer("]");
}
} catch (Exception e) {
throw new FHIRValidationException("Error retrieving profile configuration.", e);
}

// Validate asserted profiles if necessary:
// - if 'atLeastOne' is a non-empty list OR
// - if 'notAllowed' is a non-empty list OR
// - if 'allowUnknown' is set to false
if (!notAllowedProfiles.isEmpty() || !atLeastOneProfiles.isEmpty() || !allowUnknown) {
// - if 'allowUnknown' is set to false OR
// - if 'defaultVersions' exists (empty or not)
if (!notAllowedProfiles.isEmpty() || !atLeastOneProfiles.isEmpty() || !allowUnknown || defaultVersionsSpecified) {
List<Issue> issues = new ArrayList<>();
boolean validProfileFound = false;
boolean defaultVersionUsed = false;
List<Canonical> defaultVersionAssertedProfiles = new ArrayList<>();;

// Get the profiles asserted for this resource
List<String> resourceAssertedProfiles = ProfileSupport.getResourceAssertedProfiles(resource);
if (log.isLoggable(Level.FINE)) {
log.fine("Asserted profiles: " + resourceAssertedProfiles);
}

// Validate the asserted profiles.
// For 'atLeastOne' profiles, check that at least one asserted profile is in the list of 'atLeastOne' profiles.
// For 'notAllowed' profiles, check that no asserted profile is in the list of 'notAllowed' profiles.
// If an 'atLeastOne' or 'notAllowed' profile specifies a version, an asserted profile must be an exact match.
// If an 'atLeastOne' or 'notAllowed' profile does not specify a version, any asserted profile of the same name
// will be a match regardless if it specifies a version or not.
// Validate the asserted profiles
for (String resourceAssertedProfile : resourceAssertedProfiles) {
if (!notAllowedProfiles.isEmpty() || !atLeastOneProfiles.isEmpty()) {
// Check if asserted profile contains a version
String strippedAssertedProfile = null;
int index = resourceAssertedProfile.indexOf("|");
if (index != -1) {
strippedAssertedProfile = resourceAssertedProfile.substring(0, index);
// Check if asserted profile contains a version
String strippedAssertedProfile = null;
int index = resourceAssertedProfile.indexOf("|");
if (index != -1) {
strippedAssertedProfile = resourceAssertedProfile.substring(0, index);
} else {
// Check if assertedProfile has a default version
String defaultVersion = defaultVersions.get(resourceAssertedProfile);
if (defaultVersion != null) {
defaultVersionUsed = true;
strippedAssertedProfile = resourceAssertedProfile;
resourceAssertedProfile = resourceAssertedProfile + "|" + defaultVersion;
}
}
defaultVersionAssertedProfiles.add(Canonical.of(resourceAssertedProfile));

// Look for exact match or match after stripping version from asserted profile
if (!notAllowedProfiles.isEmpty() || !atLeastOneProfiles.isEmpty()) {
// For 'atLeastOne' profiles, check that at least one asserted profile is in the list of 'atLeastOne' profiles.
// For 'notAllowed' profiles, check that no asserted profile is in the list of 'notAllowed' profiles.
// If an 'atLeastOne' or 'notAllowed' profile specifies a version, an asserted profile must be an exact match.
// If an 'atLeastOne' or 'notAllowed' profile does not specify a version, any asserted profile of the same name
// will be a match regardless if it specifies a version or not.
if (notAllowedProfiles.contains(resourceAssertedProfile) ||
notAllowedProfilesWithoutVersion.contains(strippedAssertedProfile)) {
// For 'notAllowed' profiles, a match means an invalid profile was found
Expand Down Expand Up @@ -2724,9 +2774,16 @@ private List<Issue> validateResource(Resource resource) throws FHIRValidationExc
if (!issues.isEmpty()) {
return issues;
}
}

return validator.validate(resource);
// If any asserted profiles have a default version specified, make a copy of the
// resource with the new asserted profile values and validate against the copy.
if (defaultVersionUsed) {
Meta metaCopy = resource.getMeta().toBuilder().profile(defaultVersionAssertedProfiles).build();
resourceToValidate = resource.toBuilder().meta(metaCopy).build();
}
}

return validator.validate(resourceToValidate);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,15 @@ public Resource getResource() {
*/
@Override
public FHIRRegistryResource getRegistryResource(Class<? extends Resource> resourceType, String url, String version) {
if (url.equals("profile1")) {
if (url.equals("profile1") && (version == null || version.equals("1"))) {
return profile1;
} else if (url.equals("profile2")) {
} else if (url.equals("profile2") && (version == null || version.equals("1"))) {
return profile2;
} else if (url.equals("profile3")) {
} else if (url.equals("profile3") && (version == null || version.equals("1"))) {
return profile3;
} else if (url.equals("profile4")) {
} else if (url.equals("profile4") && (version == null || version.equals("1"))) {
return profile4;
} else if (url.equals("profile5")) {
} else if (url.equals("profile5") && (version == null || version.equals("1"))) {
return profile5;
} else {
return null;
Expand Down
Loading

0 comments on commit 6f8c4da

Please sign in to comment.