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

io.katharsis.queryspec.DefaultQuerySpecConverter Maven / Gradle / Ivy

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

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import io.katharsis.queryParams.QueryParams;
import io.katharsis.queryParams.RestrictedPaginationKeys;
import io.katharsis.queryParams.RestrictedSortingValues;
import io.katharsis.queryParams.include.Inclusion;
import io.katharsis.queryParams.params.FilterParams;
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.information.ResourceInformation;
import io.katharsis.resource.registry.RegistryEntry;
import io.katharsis.resource.registry.ResourceRegistry;
import io.katharsis.utils.PropertyUtils;
import io.katharsis.utils.parser.TypeParser;

public class DefaultQuerySpecConverter implements QuerySpecConverter {

	private ResourceRegistry resourceRegistry;

	private TypeParser typeParser = new TypeParser();

	private FilterOperatorRegistry operatorRegistry;

	public DefaultQuerySpecConverter(ResourceRegistry resourceRegistry, FilterOperatorRegistry operatorRegistry) {
		this.resourceRegistry = resourceRegistry;
		this.operatorRegistry = operatorRegistry;
	}

	@Override
	public QuerySpec fromParams(Class rootType, QueryParams params) {
		QuerySpec querySpec = new QuerySpec(rootType);
		applyIncludedFields(querySpec, params);
		applySorting(querySpec, params);
		applyFiltering(querySpec, params);
		applyRelatedFields(querySpec, params);
		applyPaging(querySpec, params);
		return querySpec;
	}

	private Class getResourceClass(String resourceType) {
		RegistryEntry registryEntry = resourceRegistry.getEntry(resourceType);
		if (registryEntry == null) {
			throw new IllegalArgumentException("resourceType " + resourceType + " not found");
		}
		ResourceInformation resourceInformation = registryEntry.getResourceInformation();
		return resourceInformation.getResourceClass();
	}

	protected void applyPaging(QuerySpec rootQuerySpec, QueryParams queryParams) {
		Map pagination = queryParams.getPagination();
		if (pagination != null) {
			for (Map.Entry entry : pagination.entrySet()) {
				RestrictedPaginationKeys key = entry.getKey();
				if (key == RestrictedPaginationKeys.limit) {
					rootQuerySpec.setLimit(entry.getValue().longValue());
				} else if (key == RestrictedPaginationKeys.offset) {
					rootQuerySpec.setOffset(entry.getValue());
				} else {
					throw new UnsupportedOperationException("not supported: " + key);
				}
			}
		}
	}

	protected void applyFiltering(QuerySpec rootQuerySpec, QueryParams queryParams) {
		// filtering
		TypedParams filters = queryParams.getFilters();
		if (filters != null && !filters.getParams().isEmpty()) {

			for (Map.Entry typeEntry : filters.getParams().entrySet()) {
				FilterParams filterParams = typeEntry.getValue();
				Class resourceClass = getResourceClass(typeEntry.getKey());
				QuerySpec querySpec = rootQuerySpec.getOrCreateQuerySpec(resourceClass);
				for (Entry> entry : filterParams.getParams().entrySet()) {
					String pathString = entry.getKey();
					Set stringValues = entry.getValue();
					applyFilter(querySpec, pathString, stringValues);
				}
			}
		}
	}

	private void applyFilter(QuerySpec querySpec, String parameterName, Set stringValues) {
		// find operation
		FilterOperator filterOp = null;
		String attributePathString = parameterName;
		for (FilterOperator op : operatorRegistry.getAll()) {
			String opSuffix = "." + op.toString().toLowerCase().replace("_", "");
			if (parameterName.toLowerCase().endsWith(opSuffix)) {
				attributePathString = parameterName.substring(0, parameterName.length() - opSuffix.length());
				filterOp = op;
				break;
			}
		}
		if (filterOp == null) {
			filterOp = operatorRegistry.getDefaultOperator();
		}

		List attributePath = splitPath(attributePathString);

		Class attributeType = PropertyUtils.getPropertyClass(querySpec.getResourceClass(), attributePath);
		Set typedValues = new HashSet();
		for (String stringValue : stringValues) {
			@SuppressWarnings({ "unchecked", "rawtypes" })
			Object value = typeParser.parse(stringValue, (Class) attributeType);
			typedValues.add(value);
		}
		Object value = typedValues.size() == 1 ? typedValues.iterator().next() : typedValues;

		querySpec.addFilter(new FilterSpec(attributePath, filterOp, value));
	}

	private List splitPath(String pathString) {
		return Arrays.asList(pathString.split("\\."));
	}

	protected void applySorting(QuerySpec rootQuerySpec, QueryParams queryParams) {
		TypedParams sorting = queryParams.getSorting();
		if (sorting != null && !sorting.getParams().isEmpty()) {

			for (Map.Entry typeEntry : sorting.getParams().entrySet()) {
				SortingParams sortingParams = typeEntry.getValue();
				Class resourceClass = getResourceClass(typeEntry.getKey());
				QuerySpec querySpec = rootQuerySpec.getOrCreateQuerySpec(resourceClass);

				for (Map.Entry entry : sortingParams.getParams().entrySet()) {
					Direction dir = entry.getValue() == RestrictedSortingValues.desc ? Direction.DESC : Direction.ASC;
					List attributePath = splitPath(entry.getKey());
					querySpec.addSort(new SortSpec(attributePath, dir));
				}
			}
		}
	}

	protected void applyIncludedFields(QuerySpec rootQuerySpec, QueryParams queryParams) {
		TypedParams includes = queryParams.getIncludedFields();
		if (includes != null && !includes.getParams().isEmpty()) {
			for (Entry typeEntry : includes.getParams().entrySet()) {
				IncludedFieldsParams includeParams = typeEntry.getValue();
				Class resourceClass = getResourceClass(typeEntry.getKey());
				QuerySpec querySpec = rootQuerySpec.getOrCreateQuerySpec(resourceClass);

				for (String inclusion : includeParams.getParams()) {
					List attributePath = splitPath(inclusion);
					querySpec.includeField(attributePath);
				}
			}
		}
	}

	protected void applyRelatedFields(QuerySpec rootQuerySpec, QueryParams queryParams) {
		TypedParams includes = queryParams.getIncludedRelations();
		if (includes != null && !includes.getParams().isEmpty()) {

			for (Entry typeEntry : includes.getParams().entrySet()) {
				IncludedRelationsParams includeParams = typeEntry.getValue();
				Class resourceClass = getResourceClass(typeEntry.getKey());
				QuerySpec querySpec = rootQuerySpec.getOrCreateQuerySpec(resourceClass);

				for (Inclusion inclusion : includeParams.getParams()) {
					List attributePath = splitPath(inclusion.getPath());
					querySpec.includeRelation(attributePath);
				}
			}
		}
	}

}