Search in sources :

Example 1 with ParseException

use of com.yahoo.elide.core.filter.dialect.ParseException in project elide by yahoo.

the class DefaultFilterDialect method getPath.

/**
 * Parses [ author, books, publisher, name ] into [(author, books), (book, publisher), (publisher, name)].
 *
 * @param keyParts [ author, books, publisher, name ]
 * @param apiVersion The client requested version.
 * @return [(author, books), (book, publisher), (publisher, name)]
 * @throws ParseException if the filter cannot be parsed
 */
private Path getPath(final String[] keyParts, String apiVersion) throws ParseException {
    if (keyParts == null || keyParts.length <= 0) {
        throw new ParseException("Invalid filter expression");
    }
    List<Path.PathElement> path = new ArrayList<>();
    Type<?>[] types = new Type[keyParts.length];
    String type = keyParts[0];
    types[0] = dictionary.getEntityClass(type, apiVersion);
    if (types[0] == null) {
        throw new ParseException("Unknown entity in filter: " + type);
    }
    /* Extract all the paths for the associations */
    for (int i = 1; i < keyParts.length; ++i) {
        final String field = keyParts[i];
        final Type<?> entityClass = types[i - 1];
        final Type<?> fieldType = ("id".equals(field.toLowerCase(Locale.ENGLISH))) ? dictionary.getIdType(entityClass) : dictionary.getParameterizedType(entityClass, field);
        if (fieldType == null) {
            throw new ParseException("Unknown field in filter: " + field);
        }
        types[i] = fieldType;
    }
    /* Build all the Predicate path elements */
    for (int i = 0; i < types.length - 1; ++i) {
        Type typeClass = types[i];
        String fieldName = keyParts[i + 1];
        Type fieldClass = types[i + 1];
        Path.PathElement pathElement = new Path.PathElement(typeClass, fieldClass, fieldName);
        path.add(pathElement);
    }
    return new Path(path);
}
Also used : Path(com.yahoo.elide.core.Path) Type(com.yahoo.elide.core.type.Type) ArrayList(java.util.ArrayList) ParseException(com.yahoo.elide.core.filter.dialect.ParseException)

Example 2 with ParseException

use of com.yahoo.elide.core.filter.dialect.ParseException in project elide by yahoo.

the class FilterPredicateTest method parse.

private Map<String, Set<FilterPredicate>> parse(MultivaluedMap<String, String> queryParams) {
    PredicateExtractionVisitor visitor = new PredicateExtractionVisitor();
    Map<String, FilterExpression> expressionMap;
    try {
        expressionMap = strategy.parseTypedExpression("/book", queryParams, NO_VERSION);
    } catch (ParseException e) {
        throw new BadRequestException(e.getMessage());
    }
    Map<String, Set<FilterPredicate>> returnMap = new HashMap<>();
    for (Map.Entry<String, FilterExpression> entry : expressionMap.entrySet()) {
        String typeName = entry.getKey();
        FilterExpression expression = entry.getValue();
        if (!returnMap.containsKey(typeName)) {
            returnMap.put(typeName, new HashSet<>());
        }
        returnMap.get(typeName).addAll(expression.accept(visitor));
    }
    return returnMap;
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) MultivaluedHashMap(javax.ws.rs.core.MultivaluedHashMap) PredicateExtractionVisitor(com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor) BadRequestException(com.yahoo.elide.core.exceptions.BadRequestException) ParseException(com.yahoo.elide.core.filter.dialect.ParseException) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) HashMap(java.util.HashMap) Map(java.util.Map) MultivaluedHashMap(javax.ws.rs.core.MultivaluedHashMap) MultivaluedMap(javax.ws.rs.core.MultivaluedMap)

Example 3 with ParseException

use of com.yahoo.elide.core.filter.dialect.ParseException in project elide by yahoo.

the class DefaultFilterDialect method extractPredicates.

/**
 * Converts the query parameters to a list of predicates that are then conjoined or organized by type.
 *
 * @param queryParams the query params
 * @return a list of the predicates from the query params
 * @throws ParseException when a filter parameter cannot be parsed
 */
private List<FilterPredicate> extractPredicates(MultivaluedMap<String, String> queryParams, String apiVersion) throws ParseException {
    List<FilterPredicate> filterPredicates = new ArrayList<>();
    Pattern pattern = Pattern.compile("filter\\[([^\\]]+)\\](\\[([^\\]]+)\\])?");
    for (MultivaluedMap.Entry<String, List<String>> entry : queryParams.entrySet()) {
        // Match "filter[<type>.<field>]" OR "filter[<type>.<field>][<operator>]"
        String paramName = entry.getKey();
        List<String> paramValues = entry.getValue();
        Matcher matcher = pattern.matcher(paramName);
        if (!matcher.find()) {
            throw new ParseException("Invalid filter format: " + paramName);
        }
        final String[] keyParts = matcher.group(1).split("\\.");
        if (keyParts.length < 2) {
            throw new ParseException("Invalid filter format: " + paramName);
        }
        final Operator operator = (matcher.group(3) == null) ? Operator.IN : Operator.fromString(matcher.group(3));
        Path path = getPath(keyParts, apiVersion);
        List<Path.PathElement> elements = path.getPathElements();
        Path.PathElement last = elements.get(elements.size() - 1);
        final List<Object> values = new ArrayList<>();
        if (operator.isParameterized()) {
            for (String valueParams : paramValues) {
                for (String valueParam : valueParams.split(",")) {
                    values.add(CoerceUtil.coerce(valueParam, last.getFieldType()));
                }
            }
        }
        FilterPredicate filterPredicate = new FilterPredicate(path, operator, values);
        filterPredicates.add(filterPredicate);
    }
    return filterPredicates;
}
Also used : Operator(com.yahoo.elide.core.filter.Operator) Path(com.yahoo.elide.core.Path) Pattern(java.util.regex.Pattern) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) ParseException(com.yahoo.elide.core.filter.dialect.ParseException) MultivaluedMap(javax.ws.rs.core.MultivaluedMap)

Example 4 with ParseException

use of com.yahoo.elide.core.filter.dialect.ParseException in project elide by yahoo.

the class DefaultFilterDialect method parseGlobalExpression.

@Override
public FilterExpression parseGlobalExpression(String path, MultivaluedMap<String, String> filterParams, String apiVersion) throws ParseException {
    List<FilterPredicate> filterPredicates;
    filterPredicates = extractPredicates(filterParams, apiVersion);
    /* Extract the first collection in the URL */
    String normalizedPath = JsonApiParser.normalizePath(path);
    String[] pathComponents = normalizedPath.split("/");
    String firstPathComponent = "";
    if (pathComponents.length > 0) {
        firstPathComponent = pathComponents[0];
    }
    /* Comma separated filter parameters are joined with logical AND. */
    FilterExpression joinedExpression = null;
    for (FilterPredicate filterPredicate : filterPredicates) {
        Type firstClass = filterPredicate.getPath().getPathElements().get(0).getType();
        /* The first type in the predicate must match the first collection in the URL */
        if (!dictionary.getJsonAliasFor(firstClass).equals(firstPathComponent)) {
            throw new ParseException(String.format("Invalid predicate: %s", filterPredicate));
        }
        if ((filterPredicate.getOperator().equals(Operator.HASMEMBER) || filterPredicate.getOperator().equals(Operator.HASNOMEMBER)) && !FilterPredicate.isLastPathElementAssignableFrom(dictionary, filterPredicate.getPath(), COLLECTION_TYPE)) {
            throw new ParseException("Invalid Path: Last Path Element has to be a collection type");
        }
        if (joinedExpression == null) {
            joinedExpression = filterPredicate;
        } else {
            joinedExpression = new AndFilterExpression(joinedExpression, filterPredicate);
        }
    }
    return joinedExpression;
}
Also used : Type(com.yahoo.elide.core.type.Type) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) ParseException(com.yahoo.elide.core.filter.dialect.ParseException) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression)

Example 5 with ParseException

use of com.yahoo.elide.core.filter.dialect.ParseException in project elide by yahoo.

the class RequiresFilter method getRequiredFilter.

default FilterExpression getRequiredFilter(EntityDictionary dictionary) {
    Type<?> cls = dictionary.getEntityClass(getTable().getName(), getTable().getVersion());
    RSQLFilterDialect filterDialect = RSQLFilterDialect.builder().dictionary(dictionary).addDefaultArguments(false).build();
    if (StringUtils.isNotEmpty(getRequiredFilter())) {
        try {
            return filterDialect.parseFilterExpression(getRequiredFilter(), cls, false, true);
        } catch (ParseException e) {
            throw new IllegalStateException(e);
        }
    }
    return null;
}
Also used : ParseException(com.yahoo.elide.core.filter.dialect.ParseException) RSQLFilterDialect(com.yahoo.elide.core.filter.dialect.RSQLFilterDialect)

Aggregations

ParseException (com.yahoo.elide.core.filter.dialect.ParseException)5 Path (com.yahoo.elide.core.Path)2 FilterExpression (com.yahoo.elide.core.filter.expression.FilterExpression)2 FilterPredicate (com.yahoo.elide.core.filter.predicates.FilterPredicate)2 Type (com.yahoo.elide.core.type.Type)2 ArrayList (java.util.ArrayList)2 MultivaluedMap (javax.ws.rs.core.MultivaluedMap)2 BadRequestException (com.yahoo.elide.core.exceptions.BadRequestException)1 Operator (com.yahoo.elide.core.filter.Operator)1 RSQLFilterDialect (com.yahoo.elide.core.filter.dialect.RSQLFilterDialect)1 AndFilterExpression (com.yahoo.elide.core.filter.expression.AndFilterExpression)1 PredicateExtractionVisitor (com.yahoo.elide.core.filter.expression.PredicateExtractionVisitor)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 Matcher (java.util.regex.Matcher)1 Pattern (java.util.regex.Pattern)1 MultivaluedHashMap (javax.ws.rs.core.MultivaluedHashMap)1