private Supplier<Pair<Integer, JsonNode>> handleRequest(StateContext state, BiFunction<Data<Resource>, RequestScope, Boolean> handler) { Data<Resource> data = state.getJsonApiDocument().getData(); handler.apply(data, state.getRequestScope()); // TODO: figure out if we've made modifications that differ from those requested by client return () -> Pair.of(HttpStatus.SC_NO_CONTENT, null); }
@Override public Supplier<Pair<Integer, JsonNode>> handlePost(StateContext state) { RequestScope requestScope = state.getRequestScope(); JsonApiMapper mapper = requestScope.getMapper(); newObject = createObject(requestScope); parent.ifPresent(persistentResource -> persistentResource.addRelation(relationName.get(), newObject)); return () -> { JsonApiDocument returnDoc = new JsonApiDocument(); returnDoc.setData(new Data(newObject.toResource())); JsonNode responseBody = mapper.getObjectMapper().convertValue(returnDoc, JsonNode.class); return Pair.of(HttpStatus.SC_CREATED, responseBody); }; }
/** * Adds all the relation resources for a given relation path to the included block of the * JsonApiDocument. */ private void addResourcesForPath(JsonApiDocument jsonApiDocument, PersistentResource<?> rec, List<String> relationPath) { //Pop off a relation of relation path String relation = relationPath.remove(0); Optional<FilterExpression> filterExpression = rec.getRequestScope().getExpressionForRelation(rec, relation); Set<PersistentResource> collection; try { collection = rec.getRelationCheckedFiltered(relation, filterExpression, Optional.empty(), Optional.empty()); } catch (ForbiddenAccessException e) { return; } collection.forEach(resource -> { jsonApiDocument.addIncluded(resource.toResource()); //If more relations left in the path, process a level deeper if (!relationPath.isEmpty()) { //Use a copy of the relationPath to preserve the path for remaining branches of the relationship tree addResourcesForPath(jsonApiDocument, resource, new ArrayList<>(relationPath)); } }); }
@Override public boolean equals(Object obj) { if (!(obj instanceof JsonApiDocument)) { return false; } JsonApiDocument other = (JsonApiDocument) obj; Collection<Resource> resources = data.get(); if ((resources == null || other.getData().get() == null) && resources != other.getData().get()) { return false; } if (resources != null) { if (resources.size() != other.getData().get().size() || !resources.stream().allMatch(other.getData().get()::contains)) { return false; } } // TODO: Verify links and meta? if (other.getIncluded() == null) { return included.isEmpty(); } return included.stream().allMatch(other.getIncluded()::contains); } }
@Override public Supplier<Pair<Integer, JsonNode>> handleGet(StateContext state) { JsonApiDocument jsonApiDocument = new JsonApiDocument(); RequestScope requestScope = state.getRequestScope(); Optional<MultivaluedMap<String, String>> queryParams = requestScope.getQueryParams(); jsonApiDocument.setData(getData(collection)); jsonApiDocument.setMeta(meta);
/** * Handle DELETE. * * @param path the path * @param jsonApiDocument the json api document * @param opaqueUser the opaque user * @return Elide response object */ public ElideResponse delete(String path, String jsonApiDocument, Object opaqueUser) { return handleRequest(false, opaqueUser, dataStore::beginTransaction, (tx, user) -> { JsonApiDocument jsonApiDoc = StringUtils.isEmpty(jsonApiDocument) ? new JsonApiDocument() : mapper.readJsonApiDocument(jsonApiDocument); RequestScope requestScope = new RequestScope(path, jsonApiDoc, tx, user, null, elideSettings, false); BaseVisitor visitor = new DeleteVisitor(requestScope); return visit(path, requestScope, visitor); }); }
@Override public boolean equals(Object obj) { if (!(obj instanceof JsonApiDocument)) { return false; } JsonApiDocument other = (JsonApiDocument) obj; Collection<Resource> resources = data.get(); if ((resources == null || other.getData().get() == null) && resources != other.getData().get()) { return false; } if (resources != null) { if (resources.size() != other.getData().get().size() || !resources.stream().allMatch(other.getData().get()::contains)) { return false; } } // TODO: Verify links and meta? if (other.getIncluded() == null) { return included.isEmpty(); } return included.stream().allMatch(other.getIncluded()::contains); } }
@Override public Supplier<Pair<Integer, JsonNode>> handleGet(StateContext state) { JsonApiDocument jsonApiDocument = new JsonApiDocument(); RequestScope requestScope = state.getRequestScope(); Optional<MultivaluedMap<String, String>> queryParams = requestScope.getQueryParams(); jsonApiDocument.setData(getData(collection)); jsonApiDocument.setMeta(meta);
/** * Handle GET. * * @param path the path * @param queryParams the query params * @param opaqueUser the opaque user * @return Elide response object */ public ElideResponse get(String path, MultivaluedMap<String, String> queryParams, Object opaqueUser) { return handleRequest(true, opaqueUser, dataStore::beginReadTransaction, (tx, user) -> { JsonApiDocument jsonApiDoc = new JsonApiDocument(); RequestScope requestScope = new RequestScope(path, jsonApiDoc, tx, user, queryParams, elideSettings, false); BaseVisitor visitor = new GetVisitor(requestScope); return visit(path, requestScope, visitor); }); }
private Supplier<Pair<Integer, JsonNode>> handleRequest(StateContext state, BiFunction<Data<Resource>, RequestScope, Boolean> handler) { Data<Resource> data = state.getJsonApiDocument().getData(); handler.apply(data, state.getRequestScope()); // TODO: figure out if we've made modifications that differ from those requested by client return () -> Pair.of(HttpStatus.SC_NO_CONTENT, null); }
@Override public Supplier<Pair<Integer, JsonNode>> handlePost(StateContext state) { RequestScope requestScope = state.getRequestScope(); JsonApiMapper mapper = requestScope.getMapper(); newObject = createObject(requestScope); parent.ifPresent(persistentResource -> persistentResource.addRelation(relationName.get(), newObject)); return () -> { JsonApiDocument returnDoc = new JsonApiDocument(); returnDoc.setData(new Data(newObject.toResource())); JsonNode responseBody = mapper.getObjectMapper().convertValue(returnDoc, JsonNode.class); return Pair.of(HttpStatus.SC_CREATED, responseBody); }; }
/** * Handle DELETE. * * @param path the path * @param jsonApiDocument the json api document * @param opaqueUser the opaque user * @return Elide response object */ public ElideResponse delete(String path, String jsonApiDocument, Object opaqueUser) { return handleRequest(false, opaqueUser, dataStore::beginTransaction, (tx, user) -> { JsonApiDocument jsonApiDoc = StringUtils.isEmpty(jsonApiDocument) ? new JsonApiDocument() : mapper.readJsonApiDocument(jsonApiDocument); RequestScope requestScope = new RequestScope(path, jsonApiDoc, tx, user, null, elideSettings, false); BaseVisitor visitor = new DeleteVisitor(requestScope); return visit(path, requestScope, visitor); }); }
/** * Adds all the relation resources for a given relation path to the included block of the * JsonApiDocument. */ private void addResourcesForPath(JsonApiDocument jsonApiDocument, PersistentResource<?> rec, List<String> relationPath) { //Pop off a relation of relation path String relation = relationPath.remove(0); Optional<FilterExpression> filterExpression = rec.getRequestScope().getExpressionForRelation(rec, relation); Set<PersistentResource> collection; try { collection = rec.getRelationCheckedFiltered(relation, filterExpression, Optional.empty(), Optional.empty()); } catch (ForbiddenAccessException e) { return; } collection.forEach(resource -> { jsonApiDocument.addIncluded(resource.toResource()); //If more relations left in the path, process a level deeper if (!relationPath.isEmpty()) { //Use a copy of the relationPath to preserve the path for remaining branches of the relationship tree addResourcesForPath(jsonApiDocument, resource, new ArrayList<>(relationPath)); } }); }
/** * Clear all relationships for all resources in document. */ private static void clearAllExceptRelationships(JsonApiDocument doc) { Data<Resource> data = doc.getData(); if (data == null || data.get() == null) { return; } data.get().forEach(JsonApiPatch::clearAllExceptRelationships); }
protected static JsonNode getResponseBody(PersistentResource resource, RequestScope requestScope) { Optional<MultivaluedMap<String, String>> queryParams = requestScope.getQueryParams(); JsonApiDocument jsonApiDocument = new JsonApiDocument(); //TODO Make this a document processor Data<Resource> data = resource == null ? null : new Data<>(resource.toResource()); jsonApiDocument.setData(data); //TODO Iterate over set of document processors DocumentProcessor includedProcessor = new IncludedProcessor(); includedProcessor.execute(jsonApiDocument, resource, queryParams); return requestScope.getMapper().toJsonObject(jsonApiDocument); } }
/** * Handle GET. * * @param path the path * @param queryParams the query params * @param opaqueUser the opaque user * @return Elide response object */ public ElideResponse get(String path, MultivaluedMap<String, String> queryParams, Object opaqueUser) { return handleRequest(true, opaqueUser, dataStore::beginReadTransaction, (tx, user) -> { JsonApiDocument jsonApiDoc = new JsonApiDocument(); RequestScope requestScope = new RequestScope(path, jsonApiDoc, tx, user, queryParams, elideSettings, false); BaseVisitor visitor = new GetVisitor(requestScope); return visit(path, requestScope, visitor); }); }
/** * Clear all relationships for all resources in document. */ private static void clearAllExceptRelationships(JsonApiDocument doc) { Data<Resource> data = doc.getData(); if (data == null || data.get() == null) { return; } data.get().forEach(JsonApiPatch::clearAllExceptRelationships); }
protected static JsonNode getResponseBody(PersistentResource resource, RequestScope requestScope) { Optional<MultivaluedMap<String, String>> queryParams = requestScope.getQueryParams(); JsonApiDocument jsonApiDocument = new JsonApiDocument(); //TODO Make this a document processor Data<Resource> data = resource == null ? null : new Data<>(resource.toResource()); jsonApiDocument.setData(data); //TODO Iterate over set of document processors DocumentProcessor includedProcessor = new IncludedProcessor(); includedProcessor.execute(jsonApiDocument, resource, queryParams); return requestScope.getMapper().toJsonObject(jsonApiDocument); } }
JsonApiMapper mapper = requestScope.getMapper(); Data<Resource> data = doc.getData(); Collection<Resource> resources = data.get();
@Override public Supplier<Pair<Integer, JsonNode>> handleGet(StateContext state) { JsonApiDocument doc = new JsonApiDocument(); RequestScope requestScope = state.getRequestScope(); JsonApiMapper mapper = requestScope.getMapper(); doc.setData(data); doc.setData(new Data<>(new ArrayList<>())); } else if (relationshipType.isToOne()) { doc.setData(new Data<>((Resource) null)); } else { throw new IllegalStateException("Failed to GET a relationship; relationship is neither toMany nor toOne");