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: 3.0.2
Show newest version
package io.katharsis.queryParams;

import io.katharsis.jackson.exception.ParametersDeserializationException;
import io.katharsis.queryParams.include.Inclusion;
import io.katharsis.queryParams.params.*;
import io.katharsis.resource.RestrictedQueryParamsMembers;

import java.util.*;
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[Task][name]=Super task}
  • *
  • {@code GET /tasks/?filter[Task][name]=Super task&[Task][dueDate]=2015-10-01}
  • *
  • {@code GET /tasks/?filter[Task][name][$startWith]=Super task}
  • *
  • {@code GET /tasks/?filter[Task][name][][$startWith]=Super&[Task][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 = String.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[Task][name]=asc}
  • *
  • {@code GET /project/?sort[Project][shortName]=desc&sort[User][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 = String.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[Task]=name}
  • *
  • {@code GET /project/?group[User]=name.firstName&include[Project]=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[Task][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[Task]=name}
  • *
  • {@code GET /tasks/?fields[Task][]=name&fields[Task][]=dueDate}
  • *
  • {@code GET /tasks/?fields[User]=name.surname&include[Task]=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[Task][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[Task]=author}
  • *
  • {@code GET /tasks/?include[Task][]=author&include[Task][]=comments}
  • *
  • {@code GET /projects/?include[Project]=task&include[Task]=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); if (temporaryInclusionsMap.containsKey(resourceType)) { Set resourceParams = temporaryInclusionsMap.get(resourceType); resourceParams.add(new Inclusion(entry.getValue() .iterator() .next())); temporaryInclusionsMap.put(resourceType, resourceParams); } else { Set resourceParams = new LinkedHashSet<>(); resourceParams.add(new Inclusion(entry.getValue() .iterator() .next())); 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 List buildPropertyListFromEntry(Map.Entry> entry, String prefix) { String entryKey = entry.getKey() .substring(prefix.length()); String pattern = "\\w+(? matchList = new LinkedList<>(); while (matcher.find()) { matchList.add(matcher.group()); } if (matchList.size() < 1) { throw new ParametersDeserializationException("Malformed filter parameter: " + entryKey); } return matchList; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy