use of com.yahoo.elide.jsonapi.models.Resource in project elide by yahoo.
the class PersistentResourceTest method testRelationshipMissingData.
/**
* Verify that Relationship toMany cannot contain null resources, but toOne can.
*
* @throws Exception
*/
@Test
public void testRelationshipMissingData() throws Exception {
User goodUser = new TestUser("1");
@SuppressWarnings("resource") DataStoreTransaction tx = mock(DataStoreTransaction.class);
RequestScope goodScope = new RequestScope(null, null, NO_VERSION, null, tx, goodUser, null, null, UUID.randomUUID(), elideSettings);
// null resource in toMany relationship is not valid
List<Resource> idList = new ArrayList<>();
idList.add(new ResourceIdentifier("child", "3").castToResource());
idList.add(new ResourceIdentifier("child", "6").castToResource());
idList.add(null);
assertThrows(NullPointerException.class, () -> new Relationship(Collections.emptyMap(), new Data<>(idList)));
// However null toOne relationship is valid
Relationship toOneRelationship = new Relationship(Collections.emptyMap(), new Data<>((Resource) null));
assertTrue(toOneRelationship.getData().get().isEmpty());
assertNull(toOneRelationship.toPersistentResources(goodScope));
// no Data
Relationship nullRelationship = new Relationship(Collections.emptyMap(), null);
assertNull(nullRelationship.getData());
assertNull(nullRelationship.toPersistentResources(goodScope));
}
use of com.yahoo.elide.jsonapi.models.Resource in project elide by yahoo.
the class PersistentResourceTest method testSuccessfulOneToOneRelationshipAddNull.
/**
* Avoid NPE when PATCH or POST defines relationship with null id
* <pre>
* <code>
* "relationships": {
* "left": {
* "data": {
* "type": "right",
* "id": null
* }
* }
* }
* </code>
* </pre>
*/
@Test
public void testSuccessfulOneToOneRelationshipAddNull() throws Exception {
Left left = new Left();
left.setId(2);
RequestScope goodScope = buildRequestScope(tx, goodUser);
PersistentResource<Left> leftResource = new PersistentResource<>(left, "2", goodScope);
Relationship ids = new Relationship(null, new Data<>(new Resource("right", null, null, null, null, null)));
InvalidObjectIdentifierException thrown = assertThrows(InvalidObjectIdentifierException.class, () -> leftResource.updateRelation("one2one", ids.toPersistentResources(goodScope)));
assertEquals("Unknown identifier null for right", thrown.getMessage());
}
use of com.yahoo.elide.jsonapi.models.Resource in project elide by yahoo.
the class PersistentResourceTest method testTransferPermissionSuccessOnUpdateSingularRelationship.
@Test
public void testTransferPermissionSuccessOnUpdateSingularRelationship() {
example.User userModel = new example.User();
userModel.setId(1);
NoShareEntity noShare = new NoShareEntity();
/* The noshare already exists so no exception should be thrown */
userModel.setNoShare(noShare);
List<Resource> idList = new ArrayList<>();
idList.add(new ResourceIdentifier("noshare", "1").castToResource());
Relationship ids = new Relationship(null, new Data<>(idList));
when(tx.getToOneRelation(any(), eq(userModel), any(), any())).thenReturn(noShare);
when(tx.loadObject(any(), eq(1L), any())).thenReturn(noShare);
RequestScope goodScope = buildRequestScope(tx, goodUser);
PersistentResource<example.User> userResource = new PersistentResource<>(userModel, goodScope.getUUIDFor(userModel), goodScope);
boolean returnVal = userResource.updateRelation("noShare", ids.toPersistentResources(goodScope));
assertFalse(returnVal);
assertEquals(noShare, userModel.getNoShare());
}
use of com.yahoo.elide.jsonapi.models.Resource in project elide by yahoo.
the class DataDeserializer method deserialize.
@Override
public Data<Resource> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
if (node.isArray()) {
List<Resource> resources = new ArrayList<>();
for (JsonNode n : node) {
Resource r = MAPPER.convertValue(n, Resource.class);
validateResource(jsonParser, r);
resources.add(r);
}
return new Data<>(resources);
}
Resource resource = MAPPER.convertValue(node, Resource.class);
validateResource(jsonParser, resource);
return new Data<>(resource);
}
use of com.yahoo.elide.jsonapi.models.Resource 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;
}
Aggregations