Search in sources :

Example 11 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression in project elide by yahoo.

the class SplitFilterExpressionVisitorTest method testVisitOrExpression.

@Test
public void testVisitOrExpression() {
    // pure-W OR pure-W
    OrFilterExpression filterExpression = new OrFilterExpression(WHERE_PREDICATE, WHERE_PREDICATE);
    assertEquals("(playerStats.overallRating IN [foo] OR playerStats.overallRating IN [foo])", splitFilterExpressionVisitor.visitOrExpression(filterExpression).getWhereExpression().toString());
    assertNull(splitFilterExpressionVisitor.visitOrExpression(filterExpression).getHavingExpression());
    // H1 OR W1
    OrFilterExpression or = new OrFilterExpression(HAVING_PREDICATE, WHERE_PREDICATE);
    assertNull(splitFilterExpressionVisitor.visitOrExpression(or).getWhereExpression());
    assertEquals("(playerStats.highScore GT [99] OR playerStats.overallRating IN [foo])", splitFilterExpressionVisitor.visitOrExpression(or).getHavingExpression().toString());
    // (W1 AND H1) OR W2
    AndFilterExpression and = new AndFilterExpression(WHERE_PREDICATE, HAVING_PREDICATE);
    or = new OrFilterExpression(and, WHERE_PREDICATE);
    assertNull(splitFilterExpressionVisitor.visitOrExpression(or).getWhereExpression());
    assertEquals("((playerStats.overallRating IN [foo] AND playerStats.highScore GT [99]) OR playerStats.overallRating IN [foo])", splitFilterExpressionVisitor.visitOrExpression(or).getHavingExpression().toString());
}
Also used : OrFilterExpression(com.yahoo.elide.core.filter.expression.OrFilterExpression) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) Test(org.junit.jupiter.api.Test)

Example 12 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression in project elide by yahoo.

the class PersistentResource method getRelation.

/**
 * Load a relation from the PersistentResource.
 *
 * @param relationship the relation
 * @param ids          a list of object identifiers to optionally load.  Can be empty.
 * @return PersistentResource relation
 */
public Observable<PersistentResource> getRelation(List<String> ids, com.yahoo.elide.core.request.Relationship relationship) {
    FilterExpression filterExpression = Optional.ofNullable(relationship.getProjection().getFilterExpression()).orElse(null);
    assertPropertyExists(relationship.getName());
    Type<?> entityType = dictionary.getParameterizedType(getResourceType(), relationship.getName());
    Set<PersistentResource> newResources = new LinkedHashSet<>();
    /* If this is a bulk edit request and the ID we are fetching for is newly created... */
    if (!ids.isEmpty()) {
        // Fetch our set of new resources that we know about since we can't find them in the datastore
        newResources = requestScope.getNewPersistentResources().stream().filter(resource -> entityType.isAssignableFrom(resource.getResourceType()) && ids.contains(resource.getUUID().orElse(""))).collect(Collectors.toSet());
        FilterExpression idExpression = buildIdFilterExpression(ids, entityType, dictionary, requestScope);
        // Combine filters if necessary
        filterExpression = Optional.ofNullable(relationship.getProjection().getFilterExpression()).map(fe -> (FilterExpression) new AndFilterExpression(idExpression, fe)).orElse(idExpression);
    }
    // TODO: Filter on new resources?
    // TODO: Update pagination to subtract the number of new resources created?
    Observable<PersistentResource> existingResources = filter(ReadPermission.class, Optional.ofNullable(filterExpression), relationship.getProjection().getRequestedFields(), getRelation(relationship.copyOf().projection(relationship.getProjection().copyOf().filterExpression(filterExpression).build()).build(), true));
    // TODO: Sort again in memory now that two sets are glommed together?
    Observable<PersistentResource> allResources = Observable.fromIterable(newResources).mergeWith(existingResources);
    Set<String> foundIds = new HashSet<>();
    allResources = allResources.doOnNext((resource) -> {
        String id = (String) (resource.getUUID().orElseGet(resource::getId));
        if (ids.contains(id)) {
            foundIds.add(id);
        }
    });
    allResources = allResources.doOnComplete(() -> {
        Set<String> missedIds = Sets.difference(new HashSet<>(ids), foundIds);
        if (!missedIds.isEmpty()) {
            throw new InvalidObjectIdentifierException(missedIds.toString(), relationship.getName());
        }
    });
    return allResources;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Resource(com.yahoo.elide.jsonapi.models.Resource) Data(com.yahoo.elide.jsonapi.models.Data) StringUtils(org.apache.commons.lang3.StringUtils) UpdatePermission(com.yahoo.elide.annotation.UpdatePermission) ClassType(com.yahoo.elide.core.type.ClassType) DeletePermission(com.yahoo.elide.annotation.DeletePermission) Argument(com.yahoo.elide.core.request.Argument) InvalidSyntaxException(com.yahoo.elide.core.audit.InvalidSyntaxException) Map(java.util.Map) DataStoreIterable(com.yahoo.elide.core.datastore.DataStoreIterable) LifeCycleHookBinding(com.yahoo.elide.annotation.LifeCycleHookBinding) EntityBinding(com.yahoo.elide.core.dictionary.EntityBinding) NonNull(lombok.NonNull) Collection(java.util.Collection) Set(java.util.Set) CoerceUtil(com.yahoo.elide.core.utils.coerce.CoerceUtil) Collectors(java.util.stream.Collectors) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) Sets(com.google.common.collect.Sets) Serializable(java.io.Serializable) Objects(java.util.Objects) ExpressionResult(com.yahoo.elide.core.security.permissions.ExpressionResult) List(java.util.List) Annotation(java.lang.annotation.Annotation) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) Optional(java.util.Optional) RelationshipType(com.yahoo.elide.core.dictionary.RelationshipType) Attribute(com.yahoo.elide.core.request.Attribute) InvalidAttributeException(com.yahoo.elide.core.exceptions.InvalidAttributeException) Function(java.util.function.Function) Supplier(java.util.function.Supplier) CollectionUtils(org.apache.commons.collections4.CollectionUtils) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) IterableUtils(org.apache.commons.collections4.IterableUtils) LogMessageImpl(com.yahoo.elide.core.audit.LogMessageImpl) DELETE(com.yahoo.elide.annotation.LifeCycleHookBinding.Operation.DELETE) EntityDictionary.getType(com.yahoo.elide.core.dictionary.EntityDictionary.getType) JsonIgnore(com.fasterxml.jackson.annotation.JsonIgnore) Predicates(com.google.common.base.Predicates) InternalServerErrorException(com.yahoo.elide.core.exceptions.InternalServerErrorException) CanPaginateVisitor(com.yahoo.elide.core.security.visitors.CanPaginateVisitor) Observable(io.reactivex.Observable) LogMessage(com.yahoo.elide.core.audit.LogMessage) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) LinkedHashSet(java.util.LinkedHashSet) UPDATE(com.yahoo.elide.annotation.LifeCycleHookBinding.Operation.UPDATE) DataStoreTransaction(com.yahoo.elide.core.datastore.DataStoreTransaction) VerifyFieldAccessFilterExpressionVisitor(com.yahoo.elide.core.filter.visitors.VerifyFieldAccessFilterExpressionVisitor) ChangeSpec(com.yahoo.elide.core.security.ChangeSpec) COLLECTION_TYPE(com.yahoo.elide.core.type.ClassType.COLLECTION_TYPE) Sorting(com.yahoo.elide.core.request.Sorting) InvalidEntityBodyException(com.yahoo.elide.core.exceptions.InvalidEntityBodyException) InvalidObjectIdentifierException(com.yahoo.elide.core.exceptions.InvalidObjectIdentifierException) InPredicate(com.yahoo.elide.core.filter.predicates.InPredicate) EntityProjection(com.yahoo.elide.core.request.EntityProjection) Relationship(com.yahoo.elide.jsonapi.models.Relationship) ForbiddenAccessException(com.yahoo.elide.core.exceptions.ForbiddenAccessException) ReadPermission(com.yahoo.elide.annotation.ReadPermission) BadRequestException(com.yahoo.elide.core.exceptions.BadRequestException) Pagination(com.yahoo.elide.core.request.Pagination) ResourceIdentifier(com.yahoo.elide.jsonapi.models.ResourceIdentifier) TreeMap(java.util.TreeMap) CreatePermission(com.yahoo.elide.annotation.CreatePermission) CREATE(com.yahoo.elide.annotation.LifeCycleHookBinding.Operation.CREATE) Type(com.yahoo.elide.core.type.Type) Preconditions(com.google.common.base.Preconditions) Comparator(java.util.Comparator) Collections(java.util.Collections) EMPTY_BINDING(com.yahoo.elide.core.dictionary.EntityBinding.EMPTY_BINDING) Audit(com.yahoo.elide.annotation.Audit) NonTransferable(com.yahoo.elide.annotation.NonTransferable) Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) InvalidObjectIdentifierException(com.yahoo.elide.core.exceptions.InvalidObjectIdentifierException) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 13 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression in project elide by yahoo.

the class DataStoreTransaction method loadObject.

/**
 * Loads an object by ID.  The reason we support both load by ID and load by filter is that
 * some legacy stores are optimized to load by ID.
 *
 * @param entityProjection the collection to load.
 * @param id - the ID of the object to load.
 * @param scope - the current request scope
 * @param <T> The model type being loaded.
 * It is optional for the data store to attempt evaluation.
 * @return the loaded object if it exists AND any provided security filters pass.
 */
default <T> T loadObject(EntityProjection entityProjection, Serializable id, RequestScope scope) {
    Type<?> entityClass = entityProjection.getType();
    FilterExpression filterExpression = entityProjection.getFilterExpression();
    EntityDictionary dictionary = scope.getDictionary();
    Type idType = dictionary.getIdType(entityClass);
    String idField = dictionary.getIdFieldName(entityClass);
    FilterExpression idFilter = new InPredicate(new Path.PathElement(entityClass, idType, idField), id);
    FilterExpression joinedFilterExpression = (filterExpression != null) ? new AndFilterExpression(idFilter, filterExpression) : idFilter;
    Iterable<T> results = loadObjects(entityProjection.copyOf().filterExpression(joinedFilterExpression).build(), scope);
    Iterator<T> it = results == null ? null : results.iterator();
    if (it != null && it.hasNext()) {
        T obj = it.next();
        if (!it.hasNext()) {
            return obj;
        }
        // Multiple objects with the same ID.
        throw new InvalidObjectIdentifierException(id.toString(), dictionary.getJsonAliasFor(entityClass));
    }
    return null;
}
Also used : Path(com.yahoo.elide.core.Path) InPredicate(com.yahoo.elide.core.filter.predicates.InPredicate) Type(com.yahoo.elide.core.type.Type) InvalidObjectIdentifierException(com.yahoo.elide.core.exceptions.InvalidObjectIdentifierException) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) EntityDictionary(com.yahoo.elide.core.dictionary.EntityDictionary) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression)

Example 14 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression 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 15 with AndFilterExpression

use of com.yahoo.elide.core.filter.expression.AndFilterExpression in project elide by yahoo.

the class DefaultFilterDialect method parseTypedExpression.

@Override
public Map<String, FilterExpression> parseTypedExpression(String path, MultivaluedMap<String, String> filterParams, String apiVersion) throws ParseException {
    Map<String, FilterExpression> expressionMap = new HashMap<>();
    List<FilterPredicate> filterPredicates = extractPredicates(filterParams, apiVersion);
    for (FilterPredicate filterPredicate : filterPredicates) {
        validateFilterPredicate(filterPredicate);
        String entityType = dictionary.getJsonAliasFor(filterPredicate.getEntityType());
        FilterExpression filterExpression = expressionMap.get(entityType);
        if (filterExpression != null) {
            expressionMap.put(entityType, new AndFilterExpression(filterExpression, filterPredicate));
        } else {
            expressionMap.put(entityType, filterPredicate);
        }
    }
    return expressionMap;
}
Also used : HashMap(java.util.HashMap) FilterPredicate(com.yahoo.elide.core.filter.predicates.FilterPredicate) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression) FilterExpression(com.yahoo.elide.core.filter.expression.FilterExpression) AndFilterExpression(com.yahoo.elide.core.filter.expression.AndFilterExpression)

Aggregations

AndFilterExpression (com.yahoo.elide.core.filter.expression.AndFilterExpression)34 FilterExpression (com.yahoo.elide.core.filter.expression.FilterExpression)22 OrFilterExpression (com.yahoo.elide.core.filter.expression.OrFilterExpression)21 FilterPredicate (com.yahoo.elide.core.filter.predicates.FilterPredicate)20 Test (org.junit.jupiter.api.Test)17 Path (com.yahoo.elide.core.Path)15 NotFilterExpression (com.yahoo.elide.core.filter.expression.NotFilterExpression)10 InPredicate (com.yahoo.elide.core.filter.predicates.InPredicate)10 SQLUnitTest (com.yahoo.elide.datastores.aggregation.framework.SQLUnitTest)7 Query (com.yahoo.elide.datastores.aggregation.query.Query)7 SQLTable (com.yahoo.elide.datastores.aggregation.queryengines.sql.metadata.SQLTable)7 Book (example.Book)6 Author (example.Author)5 PathElement (com.yahoo.elide.core.Path.PathElement)4 EntityDictionary (com.yahoo.elide.core.dictionary.EntityDictionary)4 Date (java.util.Date)4 DataStoreIterable (com.yahoo.elide.core.datastore.DataStoreIterable)3 RelationshipType (com.yahoo.elide.core.dictionary.RelationshipType)3 Type (com.yahoo.elide.core.type.Type)3 Day (com.yahoo.elide.datastores.aggregation.timegrains.Day)3