All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.infomaximum.cluster.graphql.schema.datafetcher.ComponentDataFetcher Maven / Gradle / Ivy

There is a newer version: 1.1.11
Show newest version
package com.infomaximum.cluster.graphql.schema.datafetcher;

import com.infomaximum.cluster.core.remote.Remotes;
import com.infomaximum.cluster.core.remote.struct.RemoteObject;
import com.infomaximum.cluster.graphql.exception.GraphQLExecutorDataFetcherException;
import com.infomaximum.cluster.graphql.executor.component.GraphQLComponentExecutor;
import com.infomaximum.cluster.graphql.executor.subscription.GraphQLSubscribeEngineImpl;
import com.infomaximum.cluster.graphql.preparecustomfield.PrepareCustomFieldUtils;
import com.infomaximum.cluster.graphql.remote.graphql.executor.RControllerGraphQLExecutor;
import com.infomaximum.cluster.graphql.schema.datafetcher.utils.ExtResult;
import com.infomaximum.cluster.graphql.schema.struct.out.RGraphQLObjectTypeField;
import com.infomaximum.cluster.graphql.struct.ContextRequest;
import com.infomaximum.cluster.graphql.struct.GSubscribeEvent;
import graphql.language.Argument;
import graphql.language.Field;
import graphql.language.VariableReference;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;

/**
 * Created by kris on 11.01.17.
 */
public class ComponentDataFetcher implements DataFetcher {

    protected final static Logger log = LoggerFactory.getLogger(ComponentDataFetcher.class);

    protected final Remotes remotes;
    protected final GraphQLComponentExecutor sdkGraphQLItemExecutor;
    protected final GraphQLSubscribeEngineImpl subscribeEngine;

    protected final String graphQLTypeName;
    protected final RGraphQLObjectTypeField rTypeGraphQLField;

    public ComponentDataFetcher(Remotes remotes, GraphQLComponentExecutor sdkGraphQLItemExecutor, GraphQLSubscribeEngineImpl subscribeEngine, String graphQLTypeName, RGraphQLObjectTypeField rTypeGraphQLField) {
        this.remotes = remotes;
        this.sdkGraphQLItemExecutor = sdkGraphQLItemExecutor;
        this.subscribeEngine = subscribeEngine;

        this.graphQLTypeName = graphQLTypeName;
        this.rTypeGraphQLField = rTypeGraphQLField;
    }

    @Override
    public Object get(DataFetchingEnvironment environment) {
        try {
            return execute(environment);
        } catch (Throwable t) {
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new RuntimeException(t);
            }
        }
    }

    protected Object execute(DataFetchingEnvironment environment) throws Throwable {
        ContextRequest context = environment.getContext();
        try {
            Object result;
            if (rTypeGraphQLField.componentUniqueId == null) {
                //У этого объекта нет родительской подсистемы - вызываем прямо тут

                if (rTypeGraphQLField.isPrepare) throw new RuntimeException("Not implemented");

                result = sdkGraphQLItemExecutor.execute(
                        environment.getSource(), graphQLTypeName, rTypeGraphQLField.name,
                        getArguments(rTypeGraphQLField, environment, context.getRequest().getQueryVariables()),
                        context
                );
            } else {
                //Этот объект принадлежит определенной подсистеме - необходимо вызывать метод удаленно именно не родительской подсистеме
                RControllerGraphQLExecutor rControllerGraphQLExecutor = remotes.getFromCKey(rTypeGraphQLField.componentUniqueId, RControllerGraphQLExecutor.class);

                RemoteObject source = null;
                if (environment.getSource() instanceof RemoteObject) {
                    source = environment.getSource();
                }

                if (rTypeGraphQLField.isPrepare) {
                    result = rControllerGraphQLExecutor.executePrepare(
                            PrepareCustomFieldUtils.getKeyField(environment),
                            source,
                            context
                    );
                } else {
                    result = rControllerGraphQLExecutor.execute(
                            source, graphQLTypeName, rTypeGraphQLField.name,
                            getArguments(rTypeGraphQLField, environment, context.getRequest().getQueryVariables()),
                            context
                    );
                }
            }

            result = ExtResult.get(result);

            if (result instanceof GSubscribeEvent.SubscribeValue) {//Подписка
                GSubscribeEvent.SubscribeValue resultSubscribeValue = (GSubscribeEvent.SubscribeValue) result;
                ObservableOnSubscribe observableOnSubscribe = new ObservableOnSubscribe() {
                    @Override
                    public void subscribe(ObservableEmitter emitter) {
                        emitter.onNext(resultSubscribeValue.value);
                        subscribeEngine.subscribe(rTypeGraphQLField.componentUniqueId, resultSubscribeValue.subscribeKey, emitter);
                    }
                };
                return Observable.create(observableOnSubscribe).toFlowable(BackpressureStrategy.LATEST);
            } else {
                return result;
            }
        } catch (Throwable t) {
            Throwable e;
            if (t instanceof InvocationTargetException) {
                e = ((InvocationTargetException) t).getTargetException();
            } else if (t instanceof ExecutionException) {
                e = t.getCause();
            } else if (t instanceof GraphQLExecutorDataFetcherException) {
                e = t.getCause();
            } else {
                e = t;
            }
            throw e;
        }
    }


    /**
     * Вытаскиваем из запроса пришедшие аргументы
     */
    protected static HashMap getArguments(RGraphQLObjectTypeField rTypeGraphQLField, DataFetchingEnvironment environment, HashMap externalVariables) {
        Field field = null;
        for (Field iField : environment.getMergedField().getFields()) {
            if (iField.getName().equals(rTypeGraphQLField.externalName)) {
                field = iField;
                break;
            }
        }
        if (field == null || field.getArguments().isEmpty()) return new HashMap<>();

        return filterArguments(field, environment.getArguments(), externalVariables.keySet());
    }

    /**
     * Фильтруем из запроса пришедшие аргументы
     */
    public static HashMap filterArguments(Field field, Map arguments, Set externalNameVariables) {
        HashMap result = new HashMap();
        for (Map.Entry entry : arguments.entrySet()) {
            Argument argument = getArgument(field, entry.getKey());
            if (argument.getValue() instanceof VariableReference) {
                //Проверим хитрую ситуацию, если аргумент в методе был зарезервирован под переменную из variables
                //но этот variable не был передан, то считаем, что этот агрумент и не собирались отправлять
                VariableReference variableReference = (VariableReference) argument.getValue();
                if (!externalNameVariables.contains(variableReference.getName())) continue;
            }
            result.put(entry.getKey(), (Serializable) entry.getValue());
        }
        return result;
    }

    private static Argument getArgument(Field field, String name) {
        for (Argument argument : field.getArguments()) {
            if (argument.getName().equals(name)) return argument;
        }
        throw new RuntimeException();//Такого быть не должно в принципе
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy