use of com.yahoo.elide.core.dictionary.EntityDictionary 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.dictionary.EntityDictionary 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;
}
use of com.yahoo.elide.core.dictionary.EntityDictionary in project elide by yahoo.
the class DefaultAsyncAPIDAOTest method setupMocks.
@BeforeEach
public void setupMocks() {
dataStore = mock(DataStore.class);
asyncQuery = mock(AsyncQuery.class);
asyncQueryResult = mock(AsyncQueryResult.class);
filter = mock(FilterExpression.class);
tx = mock(DataStoreTransaction.class);
Map<String, Class<? extends Check>> checkMappings = new HashMap<>();
EntityDictionary dictionary = EntityDictionary.builder().checks(checkMappings).build();
dictionary.bindEntity(AsyncQuery.class);
dictionary.bindEntity(AsyncQueryResult.class);
ElideSettings elideSettings = new ElideSettingsBuilder(dataStore).withEntityDictionary(dictionary).withJoinFilterDialect(RSQLFilterDialect.builder().dictionary(dictionary).build()).withSubqueryFilterDialect(RSQLFilterDialect.builder().dictionary(dictionary).build()).withISO8601Dates("yyyy-MM-dd'T'HH:mm'Z'", TimeZone.getTimeZone("UTC")).build();
elide = new Elide(elideSettings);
when(dataStore.beginTransaction()).thenReturn(tx);
asyncAPIDAO = new DefaultAsyncAPIDAO(elide.getElideSettings(), dataStore);
}
use of com.yahoo.elide.core.dictionary.EntityDictionary in project elide by yahoo.
the class AggregationDataStoreTransactionTest method testMissingRequiredTableFilter.
@Test
public void testMissingRequiredTableFilter() {
EntityDictionary dictionary = EntityDictionary.builder().build();
dictionary.bindEntity(PlayerStatsWithRequiredFilter.class);
Table table = new SQLTable(new Namespace(DEFAULT_NAMESPACE), ClassType.of(PlayerStatsWithRequiredFilter.class), dictionary);
AggregationDataStoreTransaction tx = new AggregationDataStoreTransaction(queryEngine, cache, queryLogger);
assertThrows(BadRequestException.class, () -> tx.addTableFilterArguments(table, query, dictionary));
}
use of com.yahoo.elide.core.dictionary.EntityDictionary in project elide by yahoo.
the class AggregationDataStoreTransactionTest method testMissingRequiredColumnFilter.
@Test
public void testMissingRequiredColumnFilter() throws Exception {
Type<PlayerStatsWithRequiredFilter> tableType = ClassType.of(PlayerStatsWithRequiredFilter.class);
EntityDictionary dictionary = EntityDictionary.builder().build();
dictionary.bindEntity(PlayerStatsWithRequiredFilter.class);
SQLTable table = new SQLTable(new Namespace(DEFAULT_NAMESPACE), tableType, dictionary);
Query query = Query.builder().column(SQLMetricProjection.builder().name("highScore").build()).source(table).build();
AggregationDataStoreTransaction tx = new AggregationDataStoreTransaction(queryEngine, cache, queryLogger);
assertThrows(BadRequestException.class, () -> tx.addColumnFilterArguments(table, query, dictionary));
}
Aggregations