Skip to content

Commit

Permalink
issue #1351 - Check search parameter combinations
Browse files Browse the repository at this point in the history
Signed-off-by: Troy Biesterfeld <tbieste@us.ibm.com>
  • Loading branch information
tbieste committed Oct 20, 2020
1 parent 63e7855 commit 34413f3
Show file tree
Hide file tree
Showing 5 changed files with 284 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public class FHIRConfiguration {
public static final String PROPERTY_FIELD_RESOURCES_SEARCH_PARAMETER_REQUIRED = "required";
public static final String PROPERTY_FIELD_RESOURCES_SEARCH_INCLUDES = "searchIncludes";
public static final String PROPERTY_FIELD_RESOURCES_SEARCH_REV_INCLUDES = "searchRevIncludes";
public static final String PROPERTY_FIELD_RESOURCES_SEARCH_PARAMETER_COMBINATIONS = "searchParameterCombinations";

// 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 @@ -18,16 +18,17 @@ public class SearchExceptionUtil {
private static final String ILLEGAL_EXCEPTION = "SearchParameter filter property values must be an array of String.";
private static final String ILLEGAL_ARGUMENT_EXCEPTION = "No constant with value '%s' found.";
private static final String PARSE_PARAMETER_EXCEPTION = "An error occurred while parsing parameter '%s'.";
private static final String PARSE_PARAMETERS_EXCEPTION = "An error occurred while parsing parameters.";
private static final String CHAINED_PARAMETER_EXCEPTION = "Unable to parse chained parameter: '%s'";
private static final String BADFORMAT_EXCEPTION = "Invalid Date Time Format found please use 'yyyy-mm-ddThh:mm:ss[Z|(+|-)hh:mm].'";

private SearchExceptionUtil() {
// No Op
}

/**
* creates an invalid search exception.
*
*
* @param msg
* @return
*/
Expand All @@ -38,7 +39,7 @@ public static FHIRSearchException buildNewInvalidSearchException(final String ms

/**
* creates a new parse parameter exception
*
*
* @param name
* @param e
* @return
Expand All @@ -49,9 +50,22 @@ public static FHIRSearchException buildNewParseParameterException(final String n
return new FHIRSearchException(msg, e).withIssue(ooi);
}

/**
* creates a new parse parameters exception
*
* @param name
* @param e
* @return
*/
public static FHIRSearchException buildNewParseParametersException(Exception e) {
String msg = String.format(PARSE_PARAMETERS_EXCEPTION);
OperationOutcome.Issue ooi = FHIRUtil.buildOperationOutcomeIssue(msg, IssueType.INVALID);
return new FHIRSearchException(msg, e).withIssue(ooi);
}

/**
* creates a new chained parameter exception
*
*
* @param name
* @param e
* @return
Expand All @@ -64,7 +78,7 @@ public static FHIRSearchException buildNewChainedParameterException(final String

/**
* builds an illegal state exception for a search filter execution
*
*
* @return
*/
public static IllegalStateException buildNewIllegalStateException() {
Expand All @@ -73,17 +87,17 @@ public static IllegalStateException buildNewIllegalStateException() {

/**
* builds an illegal Argument exception.
*
*
* @param val
* @return
*/
public static IllegalArgumentException buildNewIllegalArgumentException(final String val) {
return new IllegalArgumentException(String.format(ILLEGAL_ARGUMENT_EXCEPTION, val));
}

/**
* build data time format exception
*
*
* @param exception e
* @return
*/
Expand Down
113 changes: 110 additions & 3 deletions fhir-search/src/main/java/com/ibm/fhir/search/util/SearchUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,15 @@ public static FHIRSearchContext parseQueryParameters(Class<?> resourceType,
}
} // end for

try {
// Check for valid search parameter combinations
checkSearchParameterCombinations(resourceType, parameters);
} catch (FHIRSearchException se) {
throw se;
} catch (Exception e) {
throw SearchExceptionUtil.buildNewParseParametersException(e);
}

context.setSearchParameters(parameters);
return context;
}
Expand Down Expand Up @@ -913,6 +922,105 @@ private static void checkSearchParameterRestrictions(String parameterCode, Searc
}
}

/**
* Checks that the combination of search parameters is valid.
*
* @param resourceType
* the resource type
* @param parameters
* the query parameters to check
* @throws Exception
* an exception
*/
private static void checkSearchParameterCombinations(Class<?> resourceType, List<QueryParameter> parameters)
throws Exception {

List<Set<String>> validCombinations = getSearchParamterCombinations(resourceType.getSimpleName());
if (validCombinations != null) {
Set<String> searchParameterCodes = parameters.stream().map(qp -> qp.getCode()).collect(Collectors.toSet());

// Check that search parameter codes are a valid combinations
if (!validCombinations.contains(searchParameterCodes)) {
String msg;
if (searchParameterCodes.isEmpty()) {
msg = "A valid search parameter combination is required";
} else {
msg = "Search parameter combination is not valid";
}
throw SearchExceptionUtil.buildNewInvalidSearchException(msg);
}
}
}

/**
* Retrieves the search parameter combinations.
*
* @param resourceType
* the resource type
* @return list of allowed search parameter combinations
* @throws Exception
* an exception
*/
private static List<Set<String>> getSearchParamterCombinations(String resourceType) throws Exception {

List<Set<String>> spCombinations = null;

// Retrieve the "resources" config property group.
PropertyGroup rsrcsGroup = FHIRConfigHelper.getPropertyGroup(FHIRConfiguration.PROPERTY_RESOURCES);
if (rsrcsGroup != null) {
List<PropertyEntry> rsrcsEntries = rsrcsGroup.getProperties();
if (rsrcsEntries != null && !rsrcsEntries.isEmpty()) {
List<String> combinations = null;

// Try to find search parameter combinations property for matching resource type
for (PropertyEntry rsrcsEntry : rsrcsEntries) {
if (resourceType.equals(rsrcsEntry.getName())) {
PropertyGroup resourceTypeGroup = (PropertyGroup) rsrcsEntry.getValue();
if (resourceTypeGroup != null) {
combinations = resourceTypeGroup.getStringListProperty(FHIRConfiguration.PROPERTY_FIELD_RESOURCES_SEARCH_PARAMETER_COMBINATIONS);
break;
}
}
}

// Otherwise, try to find search parameter combinations property for "Resource" resource type
if (combinations == null) {
for (PropertyEntry rsrcsEntry : rsrcsEntries) {

// Check if matching resource type
if (SearchConstants.RESOURCE_RESOURCE.equals(rsrcsEntry.getName())) {
PropertyGroup resourceTypeGroup = (PropertyGroup) rsrcsEntry.getValue();
if (resourceTypeGroup != null) {
combinations =
resourceTypeGroup.getStringListProperty(FHIRConfiguration.PROPERTY_FIELD_RESOURCES_SEARCH_PARAMETER_COMBINATIONS);
break;
}
}
}
}

// Convert the combinations, which are delimited by a '+', to a list of sets
if (combinations != null) {
spCombinations = new ArrayList<>();
for (String combination : combinations) {
Set<String> combinationSet = new HashSet<>();
if (!combination.isEmpty()) {
for (String spString : combination.split("\\+")) {
if (spString.trim().isEmpty()) {
throw SearchExceptionUtil.buildNewIllegalStateException();
}
combinationSet.add(spString);
}
}
spCombinations.add(combinationSet);
}
}
}
}

return spCombinations;
}

/**
* Common logic from handling a single queryParameterValueString based on its type
*/
Expand Down Expand Up @@ -1661,7 +1769,7 @@ private static List<String> getSearchIncludeRestrictions(String resourceType) th
List<PropertyEntry> rsrcsEntries = rsrcsGroup.getProperties();
if (rsrcsEntries != null && !rsrcsEntries.isEmpty()) {

// Try find search includes property for matching resource type
// Try to find search includes property for matching resource type
for (PropertyEntry rsrcsEntry : rsrcsEntries) {
if (resourceType.equals(rsrcsEntry.getName())) {
PropertyGroup resourceTypeGroup = (PropertyGroup) rsrcsEntry.getValue();
Expand All @@ -1671,7 +1779,7 @@ private static List<String> getSearchIncludeRestrictions(String resourceType) th
}
}

// Otherwise, try find search includes property for "Resource" resource type
// Otherwise, try to find search includes property for "Resource" resource type
for (PropertyEntry rsrcsEntry : rsrcsEntries) {

// Check if matching resource type
Expand All @@ -1682,7 +1790,6 @@ private static List<String> getSearchIncludeRestrictions(String resourceType) th
}
}
}

}
}

Expand Down
Loading

0 comments on commit 34413f3

Please sign in to comment.