Skip to content

Commit

Permalink
Getting Katharsis to adhere to the Json api specification for query
Browse files Browse the repository at this point in the history
parameters katharsis-project#113

Simplify/enhance the QueryParamsParser interface by utilizing a context object
to supply the parser with the raw query parameter information from the request, as
well as a reference to the ResourceInformation of the requested resource.
  • Loading branch information
dustinstanley committed Sep 8, 2016
1 parent 660d085 commit a63ed81
Show file tree
Hide file tree
Showing 19 changed files with 809 additions and 428 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package io.katharsis.queryParams;

import io.katharsis.queryParams.context.QueryParamsParserContext;
import io.katharsis.queryParams.include.Inclusion;
import io.katharsis.queryParams.params.IncludedRelationsParams;
import io.katharsis.queryParams.params.SortingParams;
import io.katharsis.queryParams.params.TypedParams;
import io.katharsis.resource.RestrictedQueryParamsMembers;

import java.util.*;

/**
* A {@link QueryParamsParser} implementation which adheres to the JSON-API standard more strictly
* than the DefaultQueryParamsParser, at the expense of having less flexibility.
*/
public class JsonApiQueryParamsParser extends DefaultQueryParamsParser {

private static final String JSON_API_SORT_INDICATOR_DESC = "-";
private static final String JSON_API_PARAM_DELIMITER = ",";

protected TypedParams<SortingParams> parseSortingParameters(final QueryParamsParserContext context) {
String sortingKey = RestrictedQueryParamsMembers.sort.name();
Set<String> rawSortingQueryParams = parseDelimitedParameters(context.getParameterValue(sortingKey));
Map<String, SortingParams> decodedSortingMap = new LinkedHashMap<>();

if (!rawSortingQueryParams.isEmpty()) {
Map<String, RestrictedSortingValues> temporarySortingMap = new LinkedHashMap<>();

for (String sortParam : rawSortingQueryParams) {
if (sortParam.startsWith(JSON_API_SORT_INDICATOR_DESC)) {
temporarySortingMap.put(sortParam.substring(1), RestrictedSortingValues.desc);
} else {
temporarySortingMap.put(sortParam, RestrictedSortingValues.asc);
}
}

decodedSortingMap.put(context.getRequestedResourceInformation().getResourceType(),
new SortingParams(temporarySortingMap));
}

return new TypedParams<>(Collections.unmodifiableMap(decodedSortingMap));
}

protected TypedParams<IncludedRelationsParams> parseIncludedRelationsParameters(QueryParamsParserContext context) {
String includeKey = RestrictedQueryParamsMembers.include.name();
Map<String, Set<String>> inclusions = filterQueryParamsByKey(context, includeKey);

Map<String, IncludedRelationsParams> decodedInclusions = new LinkedHashMap<>();

if (inclusions.containsKey(RestrictedQueryParamsMembers.include.name())) {
Set<Inclusion> inclusionSet = new LinkedHashSet<>();
for (String inclusion : inclusions.get(RestrictedQueryParamsMembers.include.name())) {
inclusionSet.add(new Inclusion(inclusion));
}
decodedInclusions.put(context.getRequestedResourceInformation().getResourceType(),
new IncludedRelationsParams(inclusionSet));
}

return new TypedParams<>(Collections.unmodifiableMap(decodedInclusions));
}

/**
* Returns a list of all of the strings contained in parametersToParse. If any of the
* strings contained in parametersToParse is a comma-delimited list, that string will be split
* into substrings and each substring will be added to the returned set (in place of the
* delimited list).
*/
private static Set<String> parseDelimitedParameters(Set<String> parametersToParse) {
Set<String> parsedParameters = new LinkedHashSet<>();
if (parametersToParse != null && !parametersToParse.isEmpty()) {
for (String parameterToParse : parametersToParse) {
parsedParameters.addAll(Arrays.asList(parameterToParse.split(JSON_API_PARAM_DELIMITER)));
}
}
return parsedParameters;
}

/**
* Filters provided query params to one starting with provided string key. This override also splits param
* values if they are contained in a comma-delimited list.
*
* @param context used to inspect the parameters of the current request
* @param queryKey Filtering key
* @return Filtered query params
*/
@Override
protected Map<String, Set<String>> filterQueryParamsByKey(QueryParamsParserContext context, String queryKey) {
Map<String, Set<String>> filteredQueryParams = new HashMap<>();

for (String paramName : context.getParameterNames()) {
if (paramName.startsWith(queryKey)) {
filteredQueryParams.put(paramName, parseDelimitedParameters(context.getParameterValue(paramName)));
}
}
return filteredQueryParams;
}
}
Loading

0 comments on commit a63ed81

Please sign in to comment.