private boolean patch(Data<Resource> data, RequestScope requestScope) { boolean isUpdated; if (relationshipType.isToMany()) { Collection<Resource> resources = data.get(); if (resources == null) { return false; } if (!resources.isEmpty()) { isUpdated = record.updateRelation( relationshipName, new Relationship(null, new Data<>(resources)).toPersistentResources(requestScope)); } else { isUpdated = record.clearRelation(relationshipName); } } else if (relationshipType.isToOne()) { Resource resource = data.get().iterator().next(); if (resource != null) { isUpdated = record.updateRelation( relationshipName, new Relationship(null, new Data<>(resource)).toPersistentResources(requestScope)); } else { isUpdated = record.clearRelation(relationshipName); } } else { throw new IllegalStateException("Bad relationship type"); } return isUpdated; }
@Override public void handle(StateContext state, SubCollectionReadCollectionContext ctx) { String subCollection = ctx.term().getText(); EntityDictionary dictionary = state.getRequestScope().getDictionary(); try { Set<PersistentResource> collection = resource.getRelation(subCollection); // Check if exists. String entityName = dictionary.getBinding( dictionary.getParameterizedType(resource.getObject(), subCollection)); Class<?> entityClass = dictionary.getBinding(entityName); if (entityClass == null) { throw new IllegalArgumentException("Unknown type " + entityName); } final BaseState nextState; if (collection instanceof SingleElementSet) { PersistentResource record = collection.iterator().next(); nextState = new RecordTerminalState(subCollection, record); } else { nextState = new CollectionTerminalState( entityClass, Optional.of(resource), Optional.of(subCollection)); } state.setState(nextState); } catch (InvalidAttributeException e) { throw new InvalidCollectionException(subCollection); } }
@Override public boolean ok(PersistentResource<Parent> record) { Parent parent = record.getObject(); if (parent.getChildren() != null && parent.getSpouses() != null) { return true; } throw new IllegalStateException("Uninitialized " + parent); }
@Test public void testExecuteMultipleRelations() throws Exception { JsonApiDocument jsonApiDocument = new JsonApiDocument(); MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.put("include", Arrays.asList("children", "spouses")); includedProcessor.execute(jsonApiDocument, parentRecord1, Optional.of(queryParams)); List<Resource> expectedIncluded = Arrays.asList(childRecord1.toResource(), parentRecord2.toResource()); List<Resource> actualIncluded = jsonApiDocument.getIncluded(); Assert.assertEquals( actualIncluded, expectedIncluded, "Included Processor added single requested resource from 'include' query param"); }
@Override public void handle(StateContext state, SubCollectionSubCollectionContext ctx) { String id = ctx.entity().id().getText(); String subCollection = ctx.entity().term().getText(); try { state.setState(new RecordState(resource.getRelation(subCollection, id))); } catch (InvalidAttributeException e) { throw new InvalidCollectionException(subCollection); } }
@Override public void handle(StateContext state, SubCollectionToOneContext ctx) { String subCollection = ctx.term().getText(); Set<PersistentResource> single = resource.getRelation(subCollection); if (single instanceof SingleElementSet) { state.setState(new RecordState(single.iterator().next())); } else { throw new InvalidCollectionException( "Expected single element but found list for '%s'", subCollection); } }
private boolean post(Data<Resource> data, RequestScope requestScope) { Collection<Resource> resources = data.get(); if (resources == null) { return false; } resources .stream() .forEachOrdered( resource -> record.addRelation(relationshipName, resource.toPersistentResource(requestScope))); return true; }
@Test public void testExecuteMultipleNestedRelations() throws Exception { JsonApiDocument jsonApiDocument = new JsonApiDocument(); MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.put("include", Collections.singletonList("children.friends")); includedProcessor.execute(jsonApiDocument, parentRecord3, Optional.of(queryParams)); Set<Resource> expectedIncluded = Sets.newHashSet( childRecord1.toResource(), childRecord2.toResource(), childRecord3.toResource(), childRecord4.toResource()); Set<Resource> actualIncluded = new HashSet<>(jsonApiDocument.getIncluded()); Assert.assertEquals( actualIncluded, expectedIncluded, "Included Processor added multiple nested requested resource collections from 'include' query param"); }
@Test public void testExecuteSingleRelationOnCollection() throws Exception { JsonApiDocument jsonApiDocument = new JsonApiDocument(); Set<PersistentResource> parents = new HashSet<>(); parents.add(parentRecord1); parents.add(parentRecord2); MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.put("include", Collections.singletonList("children")); includedProcessor.execute(jsonApiDocument, parents, Optional.of(queryParams)); List<Resource> expectedIncluded = Arrays.asList(childRecord1.toResource(), childRecord2.toResource()); List<Resource> actualIncluded = jsonApiDocument.getIncluded(); Assert.assertEquals( actualIncluded, expectedIncluded, "Included Processor added requested resource from all records"); }
@Override public void handle(StateContext state, SubCollectionReadEntityContext ctx) { String id = ctx.entity().id().getText(); String subCollection = ctx.entity().term().getText(); try { PersistentResource nextRecord = resource.getRelation(subCollection, id); state.setState(new RecordTerminalState(subCollection, nextRecord)); } catch (InvalidAttributeException e) { throw new InvalidCollectionException(subCollection); } }
@Override public void handle(StateContext state, SubCollectionRelationshipContext ctx) { String id = ctx.entity().id().getText(); String subCollection = ctx.entity().term().getText(); User user = state.getRequestScope().getUser(); PersistentResource childRecord; try { childRecord = resource.getRelation(subCollection, id); } catch (InvalidAttributeException e) { throw new InvalidCollectionException(subCollection); } String relationName = ctx.relationship().term().getText(); try { childRecord.getRelation(relationName); } catch (InvalidAttributeException e) { throw new InvalidCollectionException(relationName); } state.setState(new RelationshipTerminalState(childRecord, relationName)); }
@Override public Supplier<Pair<Integer, JsonNode>> handleGet(StateContext state) { JsonApiDocument doc = new JsonApiDocument(); RequestScope requestScope = state.getRequestScope(); ObjectMapper mapper = requestScope.getMapper().getObjectMapper(); Optional<MultivaluedMap<String, String>> queryParams = requestScope.getQueryParams(); Map<String, Relationship> relationships = record.toResource().getRelationships(); Relationship relationship = null; if (relationships != null) { relationship = relationships.get(relationshipName); } // Handle valid relationship if (relationship != null) { // Set data Data<Resource> data = relationship.getData(); doc.setData(data); // Run include processor DocumentProcessor includedProcessor = new IncludedProcessor(); includedProcessor.execute(doc, record, queryParams); return () -> Pair.of(HttpStatus.SC_OK, mapper.convertValue(doc, JsonNode.class)); } // Handle no data for relationship if (relationshipType.isToMany()) { doc.setData(new Data<>(new ArrayList<>())); } else if (relationshipType.isToOne()) { doc.setData(new Data<>((Resource) null)); } else { throw new IllegalStateException("Failed to PATCH a relationship"); } return () -> Pair.of(HttpStatus.SC_OK, mapper.convertValue(doc, JsonNode.class)); }
public RelationshipTerminalState(PersistentResource record, String relationshipName) { this.record = record; this.relationshipType = record.getRelationshipType(relationshipName); this.relationshipName = relationshipName; }