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

com.github.dreamhead.moco.parser.model.DynamicResponseHandlerFactory Maven / Gradle / Ivy

package com.github.dreamhead.moco.parser.model;

import com.github.dreamhead.moco.CookieAttribute;
import com.github.dreamhead.moco.Moco;
import com.github.dreamhead.moco.MocoRecorders;
import com.github.dreamhead.moco.RequestExtractor;
import com.github.dreamhead.moco.ResponseElement;
import com.github.dreamhead.moco.ResponseHandler;
import com.github.dreamhead.moco.parser.ResponseHandlerFactory;
import com.github.dreamhead.moco.recorder.RecorderConfig;
import com.github.dreamhead.moco.resource.Resource;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import static com.github.dreamhead.moco.Moco.attachment;
import static com.github.dreamhead.moco.Moco.json;
import static com.github.dreamhead.moco.Moco.status;
import static com.github.dreamhead.moco.Moco.template;
import static com.github.dreamhead.moco.Moco.text;
import static com.github.dreamhead.moco.Moco.var;
import static com.github.dreamhead.moco.Moco.version;
import static com.github.dreamhead.moco.Moco.with;
import static com.github.dreamhead.moco.handler.AndResponseHandler.and;
import static com.github.dreamhead.moco.util.Iterables.head;
import static com.github.dreamhead.moco.util.Iterables.tail;
import static com.google.common.collect.ImmutableMap.copyOf;
import static com.google.common.collect.ImmutableSet.of;
import static java.lang.String.format;
import static java.util.stream.Collectors.toList;

public final class DynamicResponseHandlerFactory extends Dynamics implements ResponseHandlerFactory {
    private static final ImmutableSet RESOURCES = of("text", "file", "pathResource", "version");
    private static final ImmutableMap COMPOSITES = ImmutableMap.builder()
            .put("headers", "header")
            .put("cookies", "cookie")
            .build();

    @Override
    public ResponseHandler createResponseHandler(final ResponseSetting responseSetting) {
        List handlers = StreamSupport.stream(getFields(responseSetting.getClass()).spliterator(), false)
                .filter(isValidField(responseSetting))
                .map(fieldToResponseHandler(responseSetting))
                .collect(toList());
        return getResponseHandler(handlers);
    }

    private ResponseHandler getResponseHandler(final List handlers) {
        if (handlers.size() == 1) {
            return handlers.get(0);
        }

        return and(handlers);
    }

    private boolean isResource(final String name) {
        return RESOURCES.contains(name);
    }

    private Function fieldToResponseHandler(final ResponseSetting response) {
        return field -> {
            try {
                Object value = field.get(response);
                return createResponseHandler(field.getName(), value);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        };
    }

    private ResponseHandler createResponseHandler(final String name, final Object value) {
        if ("json".equalsIgnoreCase(name)) {
            return with(json(value));
        }

        if (isResource(name) && value instanceof TextContainer) {
            TextContainer container = (TextContainer) value;
            return with(resourceFrom(name, container));
        }

        if (value instanceof Map) {
            return createCompositeHandler(name, castToMap(value));
        }

        if ("status".equalsIgnoreCase(name)) {
            return status(Integer.parseInt(value.toString()));
        }

        if ("latency".equalsIgnoreCase(name)) {
            LatencyContainer container = (LatencyContainer) value;
            return with(container.asProcedure());
        }

        if (value instanceof ProxyContainer) {
            return ((ProxyContainer) value).asResponseHandler();
        }

        if ("attachment".equalsIgnoreCase(name)) {
            AttachmentSetting attachment = (AttachmentSetting) value;
            return attachment(attachment.getFilename(), resourceFrom(attachment));
        }

        if ("seq".equalsIgnoreCase(name)) {
            CollectionContainer sequence = (CollectionContainer) value;
            ResponseHandler[] responseHandlers = sequence.toResponseHandlers();
            return Moco.seq(head(responseHandlers), tail(responseHandlers));
        }

        if ("cycle".equalsIgnoreCase(name)) {
            CollectionContainer sequence = (CollectionContainer) value;
            ResponseHandler[] responseHandlers = sequence.toResponseHandlers();
            return Moco.cycle(head(responseHandlers), tail(responseHandlers));
        }

        if ("record".equalsIgnoreCase(name)) {
            ReplayContainer container = (ReplayContainer) value;
            RecorderConfig[] configs = container.getConfigs();
            return MocoRecorders.record(head(configs), tail(configs));
        }

        if ("replay".equalsIgnoreCase(name)) {
            ReplayContainer container = (ReplayContainer) value;
            RecorderConfig[] configs = container.getConfigs();
            return MocoRecorders.replay(head(configs), tail(configs));
        }

        throw new IllegalArgumentException(format("unknown field [%s]", name));
    }

    private Field getField(final Class clazz, final String name) throws NoSuchFieldException {
        try {
            return clazz.getDeclaredField(name);
        } catch (NoSuchFieldException e) {
            Class superclass = clazz.getSuperclass();
            if (superclass != null) {
                return getField(superclass, name);
            }
            throw e;
        }
    }

    private Resource resourceFrom(final BaseResourceSetting resourceSetting) {
        for (String resource : RESOURCES) {
            try {
                Field field = getField(resourceSetting.getClass(), resource);
                field.setAccessible(true);
                return resourceFrom(resource, (TextContainer) field.get(resourceSetting));
            } catch (Exception ignored) {
            }
        }

        throw new IllegalArgumentException("resourceSetting is expected");
    }

    private ResponseHandler createCompositeHandler(final String name, final Map map) {
        List handlers = map.entrySet()
                .stream()
                .map(toTargetHandler(name))
                .collect(toList());
        return getResponseHandler(handlers);
    }

    private Function, ResponseHandler> toTargetHandler(final String name) {
        return pair -> {
            String result = COMPOSITES.get(name);
            if (result == null) {
                throw new IllegalArgumentException("unknown composite handler name [" + name + "]");
            }

            return createResponseHandler(pair, result);
        };
    }

    private Resource getResource(final TextContainer container) {
        if (container.isForTemplate()) {
            return template(container.getText());
        }

        return text(container.getText());
    }

    private Resource getResource(final CookieContainer container) {
        if (container.isForTemplate()) {
            return template(container.getTemplate());
        }

        return text(container.getValue());
    }

    private ResponseHandler createResponseHandler(final Map.Entry pair,
                                                  final String targetMethodName) {
        Container container = pair.getValue();
        String key = pair.getKey();
        if (container instanceof TextContainer) {
            return createResponseHandler(targetMethodName, key, (TextContainer) container);
        }

        if (container instanceof CookieContainer) {
            return createCookieResponseHandler(targetMethodName, key, (CookieContainer) container);
        }

        throw new IllegalArgumentException();
    }

    private ResponseHandler createResponseHandler(final String target, final String key,
                                                  final TextContainer textContainer) {
        try {
            Method method = Moco.class.getMethod(target, String.class, Resource.class);
            return with((ResponseElement) method.invoke(null, key, getResource(textContainer)));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private ResponseHandler createCookieResponseHandler(final String target, final String key,
                                                        final CookieContainer cookieContainer) {
        try {
            Method method = Moco.class.getMethod(target, String.class, Resource.class, CookieAttribute[].class);
            return (ResponseHandler) method.invoke(null, key,
                    getResource(cookieContainer), cookieContainer.getOptions());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("unchecked")
    private Map castToMap(final Object value) {
        return (Map) value;
    }

    private Resource resourceFrom(final String name, final TextContainer container) {
        if (container.isFileContainer()) {
            return fileResource(name, (FileContainer) container);
        }

        return textResource(name, container);
    }

    private Resource textResource(final String name, final TextContainer container) {
        if (container.isRawText()) {
            return invokeTarget(name, container.getText(), Resource.class);
        }

        if (container.isForTemplate()) {
            if ("version".equalsIgnoreCase(name)) {
                return version(container.asTemplateResource());
            }

            return container.asTemplateResource(name);
        }

        throw new IllegalArgumentException(format("unknown text container:[%s]", container));
    }

    private Resource fileResource(final String name, final FileContainer fileContainer) {
        if (fileContainer.isForTemplate()) {
            if ("version".equalsIgnoreCase(name)) {
                return version(fileContainer.asTemplateResource());
            }

            return fileContainer.asTemplateResource(name);
        }

        return asFileResource(name, fileContainer);
    }

    private static Resource asResource(final String name, final Resource resource, final Optional charset) {
        if (charset.isPresent()) {
            return invokeTarget(name, resource, charset.get(),
                    Resource.class, Resource.class, Charset.class);
        }

        return invokeTarget(name, resource, Resource.class, Resource.class);
    }

    private static Resource asResource(final String name, final FileContainer fileContainer) {
        Optional charset = fileContainer.getCharset();
        String text = fileContainer.getName().getText();
        return asResource(name, text(text), charset);
    }

    public static ImmutableMap> toVariables(final Map props) {
        return copyOf(props.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e -> getRequestExtractor(e.getValue()))));
    }

    private static RequestExtractor getRequestExtractor(final TextContainer value) {
        if (value.isRawText()) {
            return var(value.getText());
        }

        return createRequestExtractor(getExtractorMethod(value.getOperation()), value.getText());
    }

    public static Resource asFileResource(final String name, final FileContainer fileContainer) {
        TextContainer filename = fileContainer.getName();
        if (filename.isRawText()) {
            return asResource(name, fileContainer);
        }

        if (filename.isForTemplate()) {
            Optional charset = fileContainer.getCharset();
            Resource resource = filename.asTemplateResource();
            return asResource(name, resource, charset);
        }

        throw new IllegalArgumentException(format("unknown file container:[%s]", fileContainer));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy