package io.github.ibuildthecloud.gdapi.request.handler; import io.github.ibuildthecloud.gdapi.condition.Condition; import io.github.ibuildthecloud.gdapi.condition.ConditionType; import io.github.ibuildthecloud.gdapi.context.ApiContext; import io.github.ibuildthecloud.gdapi.exception.ClientVisibleException; import io.github.ibuildthecloud.gdapi.id.IdFormatter; import io.github.ibuildthecloud.gdapi.model.Collection; import io.github.ibuildthecloud.gdapi.model.Field; import io.github.ibuildthecloud.gdapi.model.FieldType; import io.github.ibuildthecloud.gdapi.model.Filter; import io.github.ibuildthecloud.gdapi.model.Include; import io.github.ibuildthecloud.gdapi.model.Pagination; import io.github.ibuildthecloud.gdapi.model.Schema; import io.github.ibuildthecloud.gdapi.model.Sort; import io.github.ibuildthecloud.gdapi.model.Sort.SortOrder; import io.github.ibuildthecloud.gdapi.request.ApiRequest; import io.github.ibuildthecloud.gdapi.util.RequestUtils; import io.github.ibuildthecloud.gdapi.validation.ValidationHandler; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; public class ParseCollectionAttributes extends AbstractApiRequestHandler { Integer defaultLimit = 100; Integer maxLimit = 3000; @Override public void handle(ApiRequest request) throws IOException { if (!Schema.Method.GET.isMethod(request.getMethod())) { return; } Schema schema = request.getSchemaFactory().getSchema(request.getType()); if (schema == null) { return; } Map<String, Object> params = RequestUtils.toMap(request.getRequestObject()); parseSort(schema, params, request); parsePagination(schema, params, request); parseFilters(schema, params, request); parseIncludes(schema, params, request); } protected void parseIncludes(Schema schema, Map<String, Object> params, ApiRequest request) { List<String> links = new ArrayList<String>(); List<?> inputs = RequestUtils.toList(params.get(Collection.INCLUDE)); for (Object input : inputs) { links.add(input.toString()); } if (links.size() > 0) { request.setInclude(new Include(links.subList(0, 1))); } } protected void parseFilters(Schema schema, Map<String, Object> params, ApiRequest request) { IdFormatter formatter = ApiContext.getContext().getIdFormatter(); Map<String, Filter> filters = schema.getCollectionFilters(); Map<String, Field> fields = schema.getResourceFields(); Map<String, List<Condition>> conditions = new TreeMap<String, List<Condition>>(); for (Map.Entry<String, Object> entry : params.entrySet()) { NameAndOp nameAndOp = new NameAndOp(entry.getKey()); Filter filter = filters.get(nameAndOp.getName()); Field field = fields.get(nameAndOp.getName()); if (filter == null || field == null) { continue; } for (String mod : filter.getModifiers()) { if (nameAndOp.getOp().equals(mod)) { List<Condition> conditionList = new ArrayList<Condition>(); ConditionType conditionType = ConditionType.valueOf(nameAndOp.getOp().toUpperCase()); for (Object obj : RequestUtils.toList(entry.getValue())) { if (field.getTypeEnum() == FieldType.REFERENCE) { obj = formatter.parseId(obj.toString()); if (obj == null) { obj = "-1"; } } else if (field.getTypeEnum() == FieldType.DATE) { try { obj = ValidationHandler.convertDate(field.getName(), obj); } catch (ClientVisibleException e) { } } conditionList.add(new Condition(conditionType, obj)); } conditions.put(nameAndOp.getName(), conditionList); } } } request.setConditions(conditions); } protected void parseSort(Schema schema, Map<String, Object> params, ApiRequest request) { SortOrder orderEnum = SortOrder.ASC; String sort = RequestUtils.getSingularStringValue(Collection.SORT, params); String order = RequestUtils.getSingularStringValue(Collection.ORDER, params); if (order != null) { try { orderEnum = SortOrder.valueOf(order.trim().toUpperCase()); } catch (IllegalArgumentException e) { // ignore } } Field field = schema.getResourceFields().get(sort); if (field == null || !schema.getCollectionFilters().containsKey(sort)) { return; } URL reverseUrl = ApiContext.getUrlBuilder().reverseSort(orderEnum); if (reverseUrl == null) { return; } request.setSort(new Sort(sort, orderEnum, reverseUrl)); } protected void parsePagination(Schema schema, Map<String, Object> params, ApiRequest request) { String limit = RequestUtils.getSingularStringValue(Collection.LIMIT, params); String marker = RequestUtils.getSingularStringValue(Collection.MARKER, params); Pagination pagination = new Pagination(defaultLimit == null ? maxLimit : defaultLimit); pagination.setMarker(marker); try { if (limit != null) { Integer limitInt = new Integer(limit); if (maxLimit != null && limitInt.intValue() > maxLimit.intValue()) { limitInt = maxLimit; } if (limitInt != null && limitInt.intValue() <= 0) { if (maxLimit == null) { pagination.setLimit(null); } else { pagination.setLimit(maxLimit); } } else { pagination.setLimit(limitInt); } } } catch (NumberFormatException e) { // ignore } request.setPagination(pagination); } public Integer getDefaultLimit() { return defaultLimit; } public void setDefaultLimit(Integer defaultLimit) { this.defaultLimit = defaultLimit; } public Integer getMaxLimit() { return maxLimit; } public void setMaxLimit(Integer maxLimit) { this.maxLimit = maxLimit; } private static final class NameAndOp { String name; String op; public NameAndOp(String value) { int idx = value.lastIndexOf("_"); if (idx == -1) { this.name = value; this.op = ConditionType.EQ.getExternalForm(); } else { this.op = value.substring(idx + 1); this.name = value.substring(0, idx); } } public String getName() { return name; } public String getOp() { return op; } } }