com.spring.boxes.dollar.support.graphql.GraphqlFetchers Maven / Gradle / Ivy
The newest version!
package com.spring.boxes.dollar.support.graphql;
import static com.spring.boxes.dollar.JSONUtils.toJSON;
import static com.spring.boxes.dollar.support.graphql.GraphqlArguments.*;
import static com.spring.boxes.dollar.support.graphql.GraphqlUtils.*;
import static graphql.schema.DataFetchingEnvironmentImpl.newDataFetchingEnvironment;
import static java.util.stream.Collectors.toList;
import java.math.BigInteger;
import java.util.*;
import com.google.common.collect.Lists;
import com.netflix.graphql.dgs.DgsDataFetchingEnvironment;
import com.spring.boxes.dollar.JSONUtils;
import com.spring.boxes.dollar.enums.FetchTypeEnum;
import com.spring.boxes.dollar.support.graphql.model.FetchDirectiveArgument;
import graphql.language.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import com.google.common.collect.Maps;
import com.spring.boxes.dollar.StringUtils;
import com.spring.boxes.dollar.support.MoreStream;
import com.spring.boxes.dollar.support.aviator.AviatorInstance;
import com.spring.boxes.dollar.support.graphql.directive.DefaultDirective;
import com.spring.boxes.dollar.support.graphql.instrument.NestFutureTask;
import com.spring.boxes.dollar.support.graphql.instrument.NestInstrumentationState;
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.context.ApplicationContext;
@Slf4j
public class GraphqlFetchers {
// 组装Directive指令
public static Directive toAviatorDirective(String supply) {
if (StringUtils.isBlank(supply)) {
return null;
}
return Directive.newDirective()
.name(DefaultDirective.aviator.getName())
.argument(Argument.newArgument("supply", StringValue.newStringValue(supply).build()).build())
.build();
}
// 组装数据Fetch指令
public static Directive toFetcherDirective(FetchDirectiveArgument fetchDirectiveArgument) {
if (Objects.isNull(fetchDirectiveArgument)) {
return null;
}
List arguments = Lists.newArrayList(
Argument.newArgument("type",
IntValue.newIntValue().value(BigInteger.valueOf(fetchDirectiveArgument.getType())).build())
.build(),
Argument.newArgument("service",
StringValue.newStringValue(fetchDirectiveArgument.getService()).build())
.build(),
Argument.newArgument("supply",
StringValue.newStringValue(toJSON(fetchDirectiveArgument.getSupply())).build())
.build(),
Argument.newArgument("aviator",
BooleanValue.newBooleanValue(fetchDirectiveArgument.isAviator()).build())
.build(),
Argument.newArgument("extract",
StringValue.newStringValue(toJSON(fetchDirectiveArgument.getExtract())).build())
.build()
);
return Directive.newDirective().name(DefaultDirective.fetcher.getName()).arguments(arguments).build();
}
@SuppressWarnings("unchecked")
public static DataFetcher> getAviatorDataFetcher(DataFetcher> defaultDataFetcher, InstrumentationFieldFetchParameters parameters) {
DataFetchingEnvironment dataFetchingEnvironment = parameters.getEnvironment();
if (Objects.isNull(dataFetchingEnvironment)) {
return defaultDataFetcher;
}
Field field = dataFetchingEnvironment.getField();
String expression = getAviatorDirectiveArgument(dataFetchingEnvironment);
if (StringUtils.isBlank(expression)) {
return defaultDataFetcher;
}
return environment -> {
Object oriVal = defaultDataFetcher.get(environment);
Map variable = sourceToMap(environment);
variable.put(environment.getField().getResultKey(), oriVal);
log.debug("[@aviator] [{}] supply:{} argument:{}]", field.getName(), expression, variable);
return AviatorInstance.execute(expression, variable);
};
}
// 模型函数
@SuppressWarnings("unchecked")
public static DataFetcher> getFetcherDataFetcher(ApplicationContext applicationContext, DataFetcher> defaultDataFetcher, InstrumentationFieldFetchParameters parameters) {
DataFetchingEnvironment dataFetchingEnvironment = parameters.getEnvironment();
if (Objects.isNull(dataFetchingEnvironment)) {
return defaultDataFetcher;
}
Field field = dataFetchingEnvironment.getField();
FetchDirectiveArgument directiveArgument = getFetcherDirectiveArgument(dataFetchingEnvironment);
if (Objects.isNull(directiveArgument)) {
return defaultDataFetcher;
}
return environment -> {
Map variables = dataFetchingEnvironment.getVariables();
Map arguments =
sourceAviFetcherNewArgument(dataFetchingEnvironment, directiveArgument.getSupply(), directiveArgument.isAviator());
log.debug("[@fetcher] [{}] variables:{}, directiveArgs:{}, fetcherArgs:{}", field.getName(), toJSON(variables), toJSON(directiveArgument), toJSON(arguments));
DataFetchingEnvironment newEnvironment = newDataFetchingEnvironment(dataFetchingEnvironment)
.arguments(arguments)
.variables(variables).build();
return getDataFetcherWithNewEnvironment(applicationContext, defaultDataFetcher, newEnvironment, directiveArgument);
};
}
public static Object getDataFetcherWithNewEnvironment(ApplicationContext applicationContext, DataFetcher> defaultDataFetcher,
DataFetchingEnvironment newEnvironment,
FetchDirectiveArgument directiveArgument) {
DgsDataFetchingEnvironment dgsDataFetchingEnvironment = new DgsDataFetchingEnvironment(newEnvironment);
if (FetchTypeEnum.JAVA_EXECUTOR_BEAN.getValue() == directiveArgument.getType()) {
return GraphqlInvoker.invokeWithSpringContext(applicationContext, directiveArgument.getService(), dgsDataFetchingEnvironment);
}
if (FetchTypeEnum.JAVA_STANDARD_CLASS.getValue() == directiveArgument.getType()) {
return GraphqlInvoker.invokeWithClassName(directiveArgument.getService(), dgsDataFetchingEnvironment);
}
return defaultDataFetcher;
}
@SuppressWarnings("unchecked")
// 组装@auto标记的Fetcher并动态获取其值
@Deprecated
public static DataFetcher> autoDirectiveDataFetcher(DataFetcher> defaultDataFetcher, InstrumentationFieldFetchParameters parameters) {
DataFetchingEnvironment dataFetchingEnvironment = parameters.getEnvironment();
Field field = dataFetchingEnvironment.getField();
if (Objects.isNull(field)) {
return defaultDataFetcher;
}
Directive directive = MoreStream.getFirst(field.getDirectives(DefaultDirective.auto.getName()));
if (Objects.isNull(directive)) {
return defaultDataFetcher;
}
String supply = getArgumentStringValue(directive.getArgument("supply"),
"@auto directive illegal config: @auto(supply:'')");
Map argsMapping = StringUtils.isBlank(supply) ?
Maps.newHashMap() : JSONUtils.fromJSON(supply, Map.class, String.class, String.class);
;
NestInstrumentationState scheduleState = parameters.getInstrumentationState();
Map> sequenceTaskByNode = scheduleState.getSequenceTaskByNode();
Map> taskByPath = scheduleState.getTaskByPath();
return environment -> {
Map newArguments = new HashMap<>(dataFetchingEnvironment.getArguments());
log.debug("[@auto] field:{}, argumentMapping:{}", field.getName(), argsMapping);
List arguments = field.getArguments();
ListUtils.emptyIfNull(arguments).forEach(arg -> {
// 获取参数映射的结点
String nodeName = MapUtils.getString(argsMapping, arg.getName());
// 抽取依赖参数真实值
List taskNameForNode = sequenceTaskByNode.get(nodeName);
List> taskList = taskNameForNode.stream().map(taskByPath::get).collect(toList());
NestFutureTask
© 2015 - 2024 Weber Informatics LLC | Privacy Policy