spring-graphql DefaultGraphQlClient 源码
spring-graphql DefaultGraphQlClient 代码
文件路径:/spring-graphql/src/main/java/org/springframework/graphql/client/DefaultGraphQlClient.java
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.graphql.client;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.graphql.support.DocumentSource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Default, final {@link GraphQlClient} implementation for use with any transport.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
final class DefaultGraphQlClient implements GraphQlClient {
private final DocumentSource documentSource;
private final GraphQlClientInterceptor.Chain executeChain;
private final GraphQlClientInterceptor.SubscriptionChain executeSubscriptionChain;
DefaultGraphQlClient(
DocumentSource documentSource, GraphQlClientInterceptor.Chain executeChain,
GraphQlClientInterceptor.SubscriptionChain executeSubscriptionChain) {
Assert.notNull(documentSource, "DocumentSource is required");
Assert.notNull(executeChain, "GraphQlClientInterceptor.Chain is required");
Assert.notNull(executeSubscriptionChain, "GraphQlClientInterceptor.SubscriptionChain is required");
this.documentSource = documentSource;
this.executeChain = executeChain;
this.executeSubscriptionChain = executeSubscriptionChain;
}
@Override
public RequestSpec document(String document) {
return new DefaultRequestSpec(Mono.just(document));
}
@Override
public RequestSpec documentName(String name) {
return new DefaultRequestSpec(this.documentSource.getDocument(name));
}
/**
* The default client is unaware of transport details, and cannot implement
* mutate directly. It should be wrapped from transport aware extensions via
* {@link AbstractDelegatingGraphQlClient} that also implement mutate.
*/
@Override
public Builder<?> mutate() {
throw new UnsupportedOperationException();
}
/**
* Default {@link RequestSpec} implementation.
*/
private final class DefaultRequestSpec implements RequestSpec {
private final Mono<String> documentMono;
@Nullable
private String operationName;
private final Map<String, Object> variables = new LinkedHashMap<>();
private final Map<String, Object> attributes = new LinkedHashMap<>();
private final Map<String, Object> extensions = new LinkedHashMap<>();
DefaultRequestSpec(Mono<String> documentMono) {
Assert.notNull(documentMono, "'document' is required");
this.documentMono = documentMono;
}
@Override
public DefaultRequestSpec operationName(@Nullable String operationName) {
this.operationName = operationName;
return this;
}
@Override
public DefaultRequestSpec variable(String name, @Nullable Object value) {
this.variables.put(name, value);
return this;
}
@Override
public RequestSpec variables(Map<String, Object> variables) {
this.variables.putAll(variables);
return this;
}
@Override
public RequestSpec extension(String name, Object value) {
this.extensions.put(name, value);
return this;
}
@Override
public RequestSpec extensions(Map<String, Object> extensions) {
this.extensions.putAll(extensions);
return this;
}
@Override
public RequestSpec attribute(String name, Object value) {
this.attributes.put(name, value);
return this;
}
@Override
public RequestSpec attributes(Consumer<Map<String, Object>> attributesConsumer) {
attributesConsumer.accept(this.attributes);
return this;
}
@Override
public RetrieveSpec retrieve(String path) {
return new DefaultRetrieveSpec(execute(), path);
}
@Override
public RetrieveSubscriptionSpec retrieveSubscription(String path) {
return new DefaultRetrieveSubscriptionSpec(executeSubscription(), path);
}
@Override
public Mono<ClientGraphQlResponse> execute() {
return initRequest().flatMap(request -> executeChain.next(request)
.onErrorResume(
ex -> !(ex instanceof GraphQlClientException),
ex -> Mono.error(new GraphQlTransportException(ex, request))));
}
@Override
public Flux<ClientGraphQlResponse> executeSubscription() {
return initRequest().flatMapMany(request -> executeSubscriptionChain.next(request)
.onErrorResume(
ex -> !(ex instanceof GraphQlClientException),
ex -> Mono.error(new GraphQlTransportException(ex, request))));
}
private Mono<ClientGraphQlRequest> initRequest() {
return this.documentMono.map(document ->
new DefaultClientGraphQlRequest(document, this.operationName, this.variables, this.extensions, this.attributes));
}
}
private static class RetrieveSpecSupport {
private final String path;
protected RetrieveSpecSupport(String path) {
this.path = path;
}
/**
* Return the field if valid, or {@code null} if {@code null} without errors.
* @throws FieldAccessException for invalid response or failed field
*/
@Nullable
protected ClientResponseField getValidField(ClientGraphQlResponse response) {
ClientResponseField field = response.field(this.path);
if (!response.isValid() || field.getError() != null) {
throw new FieldAccessException(
((DefaultClientGraphQlResponse) response).getRequest(), response, field);
}
return (field.hasValue() ? field : null);
}
}
private static class DefaultRetrieveSpec extends RetrieveSpecSupport implements RetrieveSpec {
private final Mono<ClientGraphQlResponse> responseMono;
DefaultRetrieveSpec(Mono<ClientGraphQlResponse> responseMono, String path) {
super(path);
this.responseMono = responseMono;
}
@Override
public <D> Mono<D> toEntity(Class<D> entityType) {
return this.responseMono.mapNotNull(this::getValidField).map(field -> field.toEntity(entityType));
}
@Override
public <D> Mono<D> toEntity(ParameterizedTypeReference<D> entityType) {
return this.responseMono.mapNotNull(this::getValidField).map(field -> field.toEntity(entityType));
}
@Override
public <D> Mono<List<D>> toEntityList(Class<D> elementType) {
return this.responseMono.map(response -> {
ClientResponseField field = getValidField(response);
return (field != null ? field.toEntityList(elementType) : Collections.emptyList());
});
}
@Override
public <D> Mono<List<D>> toEntityList(ParameterizedTypeReference<D> elementType) {
return this.responseMono.map(response -> {
ClientResponseField field = getValidField(response);
return (field != null ? field.toEntityList(elementType) : Collections.emptyList());
});
}
}
private static class DefaultRetrieveSubscriptionSpec extends RetrieveSpecSupport implements RetrieveSubscriptionSpec {
private final Flux<ClientGraphQlResponse> responseFlux;
DefaultRetrieveSubscriptionSpec(Flux<ClientGraphQlResponse> responseFlux, String path) {
super(path);
this.responseFlux = responseFlux;
}
@Override
public <D> Flux<D> toEntity(Class<D> entityType) {
return this.responseFlux.mapNotNull(this::getValidField).map(field -> field.toEntity(entityType));
}
@Override
public <D> Flux<D> toEntity(ParameterizedTypeReference<D> entityType) {
return this.responseFlux.mapNotNull(this::getValidField).map(field -> field.toEntity(entityType));
}
@Override
public <D> Flux<List<D>> toEntityList(Class<D> elementType) {
return this.responseFlux.map(response -> {
ClientResponseField field = getValidField(response);
return (field != null ? field.toEntityList(elementType) : Collections.emptyList());
});
}
@Override
public <D> Flux<List<D>> toEntityList(ParameterizedTypeReference<D> elementType) {
return this.responseFlux.map(response -> {
ClientResponseField field = getValidField(response);
return (field != null ? field.toEntityList(elementType) : Collections.emptyList());
});
}
}
}
相关信息
相关文章
spring-graphql AbstractDelegatingGraphQlClient 源码
spring-graphql AbstractGraphQlClientBuilder 源码
spring-graphql ClientGraphQlRequest 源码
spring-graphql ClientGraphQlResponse 源码
spring-graphql ClientResponseField 源码
spring-graphql CodecDelegate 源码
spring-graphql DefaultClientGraphQlRequest 源码
spring-graphql DefaultClientGraphQlResponse 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦