use of com.yahoo.elide.core.filter.expression.FilterExpression in project elide by yahoo.
the class DataStoreLoadTest method testEqualityPredicate.
@Test
public void testEqualityPredicate() throws Exception {
DataStoreTransaction testTransaction = searchStore.beginReadTransaction();
// Case sensitive query against case insensitive index must lowercase
FilterExpression filter = filterParser.parseFilterExpression("name==drum", ClassType.of(Item.class), false);
Iterable<Object> loaded = testTransaction.loadObjects(EntityProjection.builder().type(Item.class).filterExpression(filter).build(), mockScope);
assertNull(loaded);
/* This query should hit the underlying store */
verify(wrappedTransaction, times(1)).loadObjects(any(), any());
}
use of com.yahoo.elide.core.filter.expression.FilterExpression in project elide by yahoo.
the class DataStoreSupportsFilteringTest method testUnindexedField.
@Test
public void testUnindexedField() throws Exception {
/* The field is not indexed */
DataStoreTransaction testTransaction = searchStore.beginReadTransaction();
FilterExpression filter = filterParser.parseFilterExpression("price==123", ClassType.of(Item.class), false);
EntityProjection projection = EntityProjection.builder().type(Item.class).filterExpression(filter).build();
DataStoreIterable<Object> loaded = testTransaction.loadObjects(projection, mockScope);
// The query was passed to the wrapped transaction which is a mock.
assertNull(loaded);
verify(wrappedTransaction, times(1)).loadObjects(any(), any());
}
use of com.yahoo.elide.core.filter.expression.FilterExpression in project elide by yahoo.
the class DataStoreSupportsFilteringTest method testIndexedField.
@Test
public void testIndexedField() throws Exception {
/* The field is indexed using the @Field annotation */
DataStoreTransaction testTransaction = searchStore.beginReadTransaction();
FilterExpression filter = filterParser.parseFilterExpression("description==*rum*", ClassType.of(Item.class), false);
EntityProjection projection = EntityProjection.builder().type(Item.class).filterExpression(filter).build();
DataStoreIterable<Object> loaded = testTransaction.loadObjects(projection, mockScope);
assertFalse(loaded.needsInMemoryFilter());
assertFalse(loaded.needsInMemoryPagination());
assertFalse(loaded.needsInMemorySort());
verify(wrappedTransaction, times(0)).loadObjects(any(), any());
}
use of com.yahoo.elide.core.filter.expression.FilterExpression in project elide by yahoo.
the class PersistentResource method loadRecords.
/**
* Load a collection from the datastore.
*
* @param projection the projection to load
* @param requestScope the request scope
* @param ids a list of object identifiers to optionally load. Can be empty.
* @return a filtered collection of resources loaded from the datastore.
*/
public static Observable<PersistentResource> loadRecords(EntityProjection projection, List<String> ids, RequestScope requestScope) {
Type<?> loadClass = projection.getType();
Pagination pagination = projection.getPagination();
Sorting sorting = projection.getSorting();
FilterExpression filterExpression = projection.getFilterExpression();
EntityDictionary dictionary = requestScope.getDictionary();
DataStoreTransaction tx = requestScope.getTransaction();
if (shouldSkipCollection(loadClass, ReadPermission.class, requestScope, projection.getRequestedFields())) {
if (ids.isEmpty()) {
return Observable.empty();
}
throw new InvalidObjectIdentifierException(ids.toString(), dictionary.getJsonAliasFor(loadClass));
}
Set<String> requestedFields = projection.getRequestedFields();
if (pagination != null && !pagination.isDefaultInstance() && !CanPaginateVisitor.canPaginate(loadClass, dictionary, requestScope, requestedFields)) {
throw new BadRequestException(String.format("Cannot paginate %s", dictionary.getJsonAliasFor(loadClass)));
}
Set<PersistentResource> newResources = new LinkedHashSet<>();
if (!ids.isEmpty()) {
String typeAlias = dictionary.getJsonAliasFor(loadClass);
newResources = requestScope.getNewPersistentResources().stream().filter(resource -> typeAlias.equals(resource.getTypeName()) && ids.contains(resource.getUUID().orElse(""))).collect(Collectors.toSet());
FilterExpression idExpression = buildIdFilterExpression(ids, loadClass, dictionary, requestScope);
// Combine filters if necessary
filterExpression = Optional.ofNullable(filterExpression).map(fe -> (FilterExpression) new AndFilterExpression(idExpression, fe)).orElse(idExpression);
}
Optional<FilterExpression> permissionFilter = getPermissionFilterExpression(loadClass, requestScope, requestedFields);
if (permissionFilter.isPresent()) {
if (filterExpression != null) {
filterExpression = new AndFilterExpression(filterExpression, permissionFilter.get());
} else {
filterExpression = permissionFilter.get();
}
}
EntityProjection modifiedProjection = projection.copyOf().filterExpression(filterExpression).sorting(sorting).pagination(pagination).build();
Observable<PersistentResource> existingResources = filter(ReadPermission.class, Optional.ofNullable(modifiedProjection.getFilterExpression()), projection.getRequestedFields(), Observable.fromIterable(new PersistentResourceSet(tx.loadObjects(modifiedProjection, requestScope), requestScope)));
// 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(), dictionary.getJsonAliasFor(loadClass));
}
});
return allResources;
}
use of com.yahoo.elide.core.filter.expression.FilterExpression in project elide by yahoo.
the class PersistentResource method loadRecord.
/**
* Load an single entity from the DB.
*
* @param projection What to load from the DB.
* @param id the id
* @param requestScope the request scope
* @param <T> type of resource
* @return resource persistent resource
* @throws InvalidObjectIdentifierException the invalid object identifier exception
*/
@SuppressWarnings("resource")
@NonNull
public static <T> PersistentResource<T> loadRecord(EntityProjection projection, String id, RequestScope requestScope) throws InvalidObjectIdentifierException {
Preconditions.checkNotNull(projection);
Preconditions.checkNotNull(id);
Preconditions.checkNotNull(requestScope);
DataStoreTransaction tx = requestScope.getTransaction();
EntityDictionary dictionary = requestScope.getDictionary();
Type<?> loadClass = projection.getType();
// Check the resource cache if exists
Object obj = requestScope.getObjectById(loadClass, id);
if (obj == null) {
// try to load object
Optional<FilterExpression> permissionFilter = getPermissionFilterExpression(loadClass, requestScope, projection.getRequestedFields());
Type<?> idType = dictionary.getIdType(loadClass);
projection = projection.copyOf().filterExpression(permissionFilter.orElse(null)).build();
obj = tx.loadObject(projection, (Serializable) CoerceUtil.coerce(id, idType), requestScope);
if (obj == null) {
throw new InvalidObjectIdentifierException(id, dictionary.getJsonAliasFor(loadClass));
}
}
PersistentResource<T> resource = new PersistentResource<>((T) obj, requestScope.getUUIDFor(obj), requestScope);
// No need to have read access for a newly created object
if (!requestScope.getNewResources().contains(resource)) {
resource.checkFieldAwarePermissions(ReadPermission.class, projection.getRequestedFields());
}
return resource;
}
Aggregations