All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.katharsis.queryParams.QueryParams Maven / Gradle / Ivy

There is a newer version: 2.6.3
Show newest version
package io.katharsis.queryParams;

import io.katharsis.jackson.exception.ParametersDeserializationException;
import io.katharsis.queryParams.include.Inclusion;
import io.katharsis.queryParams.params.FilterParams;
import io.katharsis.queryParams.params.GroupingParams;
import io.katharsis.queryParams.params.IncludedFieldsParams;
import io.katharsis.queryParams.params.IncludedRelationsParams;
import io.katharsis.queryParams.params.SortingParams;
import io.katharsis.queryParams.params.TypedParams;
import io.katharsis.resource.RestrictedQueryParamsMembers;
import io.katharsis.utils.StringUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Contains a set of parameters passed along with the request.
 */
public class QueryParams {
    private TypedParams filters;
    private TypedParams sorting;
    private TypedParams grouping;
    private TypedParams includedFields;
    private TypedParams includedRelations;
    private Map pagination;


    /**
     * Important! Katharsis implementation differs form JSON API
     * definition of filtering
     * in order to fit standard query parameter serializing strategy and maximize effective processing of data.
     * 

* Filter params can be send with following format (Katharsis does not specify or implement any operators):
* filter[ResourceType][property|operator]([property|operator])* = "value"
*

* Examples of accepted filtering of resources: *

    *
  • {@code GET /tasks/?filter[tasks][name]=Super task}
  • *
  • {@code GET /tasks/?filter[tasks][name]=Super task&filter[tasks][dueDate]=2015-10-01}
  • *
  • {@code GET /tasks/?filter[tasks][name][$startWith]=Super task}
  • *
  • {@code GET /tasks/?filter[tasks][name][][$startWith]=Super&filter[tasks][name][][$endWith]=task}
  • *
* * @return {@link TypedParams} Map of filtering params passed to a request grouped by type of resource */ public TypedParams getFilters() { return filters; } void setFilters(Map> filters) { Map>> temporaryFiltersMap = new LinkedHashMap(); for (Map.Entry> entry : filters.entrySet()) { List propertyList = buildPropertyListFromEntry(entry, RestrictedQueryParamsMembers.filter.name()); String resourceType = propertyList.get(0); String propertyPath = StringUtils.join(".", propertyList.subList(1, propertyList.size())); if (temporaryFiltersMap.containsKey(resourceType)) { Map> resourceParams = temporaryFiltersMap.get(resourceType); resourceParams.put(propertyPath, Collections.unmodifiableSet(entry.getValue())); } else { Map> resourceParams = new LinkedHashMap(); temporaryFiltersMap.put(resourceType, resourceParams); resourceParams.put(propertyPath, entry.getValue()); } } Map decodedFiltersMap = new LinkedHashMap(); for (Map.Entry>> resourceTypesMap : temporaryFiltersMap.entrySet()) { Map> filtersMap = Collections.unmodifiableMap(resourceTypesMap.getValue()); decodedFiltersMap.put(resourceTypesMap.getKey(), new FilterParams(filtersMap)); } this.filters = new TypedParams(Collections.unmodifiableMap(decodedFiltersMap)); } /** * Important! Katharsis implementation differs form JSON API * definition of sorting * in order to fit standard query parameter serializing strategy and maximize effective processing of data. *

* Sort params can be send with following format:
* sort[ResourceType][property]([property])* = "asc|desc" *

* Examples of accepted sorting of resources: *

    *
  • {@code GET /tasks/?sort[tasks][name]=asc}
  • *
  • {@code GET /project/?sort[projects][shortName]=desc&sort[users][name][firstName]=asc}
  • *
* * @return {@link TypedParams} Map of sorting params passed to request grouped by type of resource */ public TypedParams getSorting() { return sorting; } void setSorting(Map> sorting) { Map> temporarySortingMap = new LinkedHashMap(); for (Map.Entry> entry : sorting.entrySet()) { List propertyList = buildPropertyListFromEntry(entry, RestrictedQueryParamsMembers.sort.name()); String resourceType = propertyList.get(0); String propertyPath = StringUtils.join(".", propertyList.subList(1, propertyList.size())); if (temporarySortingMap.containsKey(resourceType)) { Map resourceParams = temporarySortingMap.get(resourceType); resourceParams.put(propertyPath, RestrictedSortingValues.valueOf(entry.getValue() .iterator() .next())); } else { Map resourceParams = new HashMap(); temporarySortingMap.put(resourceType, resourceParams); resourceParams.put(propertyPath, RestrictedSortingValues.valueOf(entry.getValue() .iterator() .next())); } } Map decodedSortingMap = new LinkedHashMap(); for (Map.Entry> resourceTypesMap : temporarySortingMap.entrySet ()) { Map sortingMap = Collections.unmodifiableMap(resourceTypesMap.getValue()); decodedSortingMap.put(resourceTypesMap.getKey(), new SortingParams(sortingMap)); } this.sorting = new TypedParams(Collections.unmodifiableMap(decodedSortingMap)); } /** * Important: Grouping itself is not specified by JSON API itself, but the * keyword and format it reserved for today and future use in Katharsis. *

* Group params can be send with following format:
* group[ResourceType] = "property(.property)*" *

* Examples of accepted grouping of resources: *

    *
  • {@code GET /tasks/?group[tasks]=name}
  • *
  • {@code GET /project/?group[users]=name.firstName&include[projects]=team}
  • *
* * @return {@link Map} Map of grouping params passed to request grouped by type of resource */ public TypedParams getGrouping() { return grouping; } void setGrouping(Map> grouping) { Map> temporaryGroupingMap = new LinkedHashMap(); for (Map.Entry> entry : grouping.entrySet()) { List propertyList = buildPropertyListFromEntry(entry, RestrictedQueryParamsMembers.group.name()); if (propertyList.size() > 1) { throw new ParametersDeserializationException("Exceeded maximum level of nesting of 'group' parameter " + "(1) eg. group[tasks][name] <-- #2 level and more are not allowed"); } String resourceType = propertyList.get(0); if (temporaryGroupingMap.containsKey(resourceType)) { Set resourceParams = temporaryGroupingMap.get(resourceType); resourceParams.addAll(entry.getValue()); temporaryGroupingMap.put(resourceType, resourceParams); } else { Set resourceParams = new LinkedHashSet(); resourceParams.addAll(entry.getValue()); temporaryGroupingMap.put(resourceType, resourceParams); } } Map decodedGroupingMap = new LinkedHashMap(); for (Map.Entry> resourceTypesMap : temporaryGroupingMap.entrySet()) { Set groupingSet = Collections.unmodifiableSet(resourceTypesMap.getValue()); decodedGroupingMap.put(resourceTypesMap.getKey(), new GroupingParams(groupingSet)); } this.grouping = new TypedParams(Collections.unmodifiableMap(decodedGroupingMap)); } /** * Important! Katharsis implementation sets on strategy of pagination whereas JSON API * definition of pagination * is agnostic about pagination strategies. *

* Pagination params can be send with following format:
* page[offset|limit] = "value", where value is an integer *

* Examples of accepted grouping of resources: *

    *
  • {@code GET /projects/?page[offset]=0&page[limit]=10}
  • *
* * @return {@link Map} Map of pagination keys passed to request */ public Map getPagination() { return pagination; } void setPagination(Map> pagination) { Map decodedPagination = new LinkedHashMap(); for (Map.Entry> entry : pagination.entrySet()) { List propertyList = buildPropertyListFromEntry(entry, RestrictedQueryParamsMembers.page.name()); if (propertyList.size() > 1) { throw new ParametersDeserializationException("Exceeded maximum level of nesting of 'page' parameter " + "(1) eg. page[offset][minimal] <-- #2 level and more are not allowed"); } String resourceType = propertyList.get(0); decodedPagination.put(RestrictedPaginationKeys.valueOf(resourceType), Integer.parseInt(entry .getValue() .iterator() .next())); } this.pagination = Collections.unmodifiableMap(decodedPagination); } /** * Important! Katharsis implementation differs form JSON API * definition of sparse field set * in order to fit standard query parameter serializing strategy and maximize effective processing of data. *

* Sparse field set params can be send with following format:
* fields[ResourceType] = "property(.property)*"
*

* Examples of accepted sparse field sets of resources: *

    *
  • {@code GET /tasks/?fields[tasks]=name}
  • *
  • {@code GET /tasks/?fields[tasks][]=name&fields[tasks][]=dueDate}
  • *
  • {@code GET /tasks/?fields[users]=name.surname&include[tasks]=author}
  • *
* * @return {@link TypedParams} Map of sparse field set params passed to a request grouped by type of resource */ public TypedParams getIncludedFields() { return includedFields; } void setIncludedFields(Map> sparse) { Map> temporarySparseMap = new LinkedHashMap(); for (Map.Entry> entry : sparse.entrySet()) { List propertyList = buildPropertyListFromEntry(entry, RestrictedQueryParamsMembers.fields.name()); if (propertyList.size() > 1) { throw new ParametersDeserializationException("Exceeded maximum level of nesting of 'fields' " + "parameter (1) eg. fields[tasks][name] <-- #2 level and more are not allowed"); } String resourceType = propertyList.get(0); if (temporarySparseMap.containsKey(resourceType)) { Set resourceParams = temporarySparseMap.get(resourceType); resourceParams.addAll(entry.getValue()); temporarySparseMap.put(resourceType, resourceParams); } else { Set resourceParams = new LinkedHashSet(); resourceParams.addAll(entry.getValue()); temporarySparseMap.put(resourceType, resourceParams); } } Map decodedSparseMap = new LinkedHashMap(); for (Map.Entry> resourceTypesMap : temporarySparseMap.entrySet()) { Set sparseSet = Collections.unmodifiableSet(resourceTypesMap.getValue()); decodedSparseMap.put(resourceTypesMap.getKey(), new IncludedFieldsParams(sparseSet)); } this.includedFields = new TypedParams(Collections.unmodifiableMap(decodedSparseMap)); } /** * Important! Katharsis implementation differs form JSON API * definition of includes * in order to fit standard query parameter serializing strategy and maximize effective processing of data. *

* Included field set params can be send with following format:
* include[ResourceType] = "property(.property)*"
*

* Examples of accepted sparse field sets of resources: *

    *
  • {@code GET /tasks/?include[tasks]=author}
  • *
  • {@code GET /tasks/?include[tasks][]=author&include[tasks][]=comments}
  • *
  • {@code GET /projects/?include[projects]=task&include[tasks]=comments}
  • *
* * @return {@link TypedParams} Map of sparse field set params passed to a request grouped by type of resource */ public TypedParams getIncludedRelations() { return includedRelations; } void setIncludedRelations(Map> inclusions) { Map> temporaryInclusionsMap = new LinkedHashMap(); for (Map.Entry> entry : inclusions.entrySet()) { List propertyList = buildPropertyListFromEntry(entry, RestrictedQueryParamsMembers.include.name()); if (propertyList.size() > 1) { throw new ParametersDeserializationException("Exceeded maximum level of nesting of 'include' " + "parameter (1)"); } String resourceType = propertyList.get(0); Set resourceParams; if (temporaryInclusionsMap.containsKey(resourceType)) { resourceParams = temporaryInclusionsMap.get(resourceType); } else { resourceParams = new LinkedHashSet(); } for(String path : entry.getValue()) { resourceParams.add(new Inclusion(path)); } temporaryInclusionsMap.put(resourceType, resourceParams); } Map decodedInclusions = new LinkedHashMap(); for (Map.Entry> resourceTypesMap : temporaryInclusionsMap.entrySet()) { Set inclusionSet = Collections.unmodifiableSet(resourceTypesMap.getValue()); decodedInclusions.put(resourceTypesMap.getKey(), new IncludedRelationsParams(inclusionSet)); } this.includedRelations = new TypedParams(Collections.unmodifiableMap(decodedInclusions)); } private static List buildPropertyListFromEntry(Map.Entry> entry, String prefix) { String entryKey = entry.getKey() .substring(prefix.length()); String pattern = "[^\\]\\[]+(? matchList = new LinkedList(); while (matcher.find()) { matchList.add(matcher.group()); } if (matchList.isEmpty()) { throw new ParametersDeserializationException("Malformed filter parameter: " + entryKey); } return matchList; } @Override public String toString() { return "QueryParams{" + "filters=" + filters + ", sorting=" + sorting + ", grouping=" + grouping + ", includedFields=" + includedFields + ", includedRelations=" + includedRelations + ", pagination=" + pagination + '}'; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy