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

com.consol.citrus.dsl.builder.SendMessageBuilder Maven / Gradle / Ivy

There is a newer version: 3.4.1
Show newest version
/*
 * Copyright 2006-2015 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
 *
 *     http://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 com.consol.citrus.dsl.builder;

import com.consol.citrus.Citrus;
import com.consol.citrus.TestAction;
import com.consol.citrus.actions.SendMessageAction;
import com.consol.citrus.dsl.actions.DelegatingTestAction;
import com.consol.citrus.endpoint.Endpoint;
import com.consol.citrus.exceptions.CitrusRuntimeException;
import com.consol.citrus.message.Message;
import com.consol.citrus.message.MessageType;
import com.consol.citrus.util.FileUtils;
import com.consol.citrus.validation.builder.*;
import com.consol.citrus.validation.json.*;
import com.consol.citrus.validation.xml.XpathMessageConstructionInterceptor;
import com.consol.citrus.validation.xml.XpathPayloadVariableExtractor;
import com.consol.citrus.variable.MessageHeaderVariableExtractor;
import com.consol.citrus.variable.dictionary.DataDictionary;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.XmlMappingException;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.xml.transform.StringResult;

import java.io.IOException;

/**
 * Action builder creates a send message action with several message payload and header
 * constructing build methods.
 * 
 * @author Christoph Deppisch
 * @since 2.3
 */
public class SendMessageBuilder extends AbstractTestActionBuilder> {

    /** Self reference for generics support */
    private final T self;

    /** Message type for this action builder */
    private String messageType = Citrus.DEFAULT_MESSAGE_TYPE;

    /** Variable extractors filled within this builder */
    private MessageHeaderVariableExtractor headerExtractor;
    private XpathPayloadVariableExtractor xpathExtractor;
    private JsonPathVariableExtractor jsonPathExtractor;

    /** Message constructing interceptor */
    private XpathMessageConstructionInterceptor xpathMessageConstructionInterceptor;
    private JsonPathMessageConstructionInterceptor jsonPathMessageConstructionInterceptor;

    /** Basic application context */
    private ApplicationContext applicationContext;

    /**
     * Default constructor with test action.
     * @param action
     */
    public SendMessageBuilder(A action) {
        this(new DelegatingTestAction(action));
    }

    /**
     * Default constructor.
     */
    public SendMessageBuilder() {
        this((A) new SendMessageAction());
    }

    /**
     * Constructor using delegate test action.
     * @param action
     */
    public SendMessageBuilder(DelegatingTestAction action) {
        super(action);
        this.self = (T) this;
    }

    /**
     * Sets the message endpoint to send messages to.
     * @param messageEndpoint
     * @return
     */
    public SendMessageBuilder endpoint(Endpoint messageEndpoint) {
        getAction().setEndpoint(messageEndpoint);
        return this;
    }

    /**
     * Sets the message endpoint uri to send messages to.
     * @param messageEndpointUri
     * @return
     */
    public SendMessageBuilder endpoint(String messageEndpointUri) {
        getAction().setEndpointUri(messageEndpointUri);
        return this;
    }

    /**
     * Sets the fork mode for this send action builder.
     * @param forkMode
     * @return
     */
    public T fork(boolean forkMode) {
        getAction().setForkMode(forkMode);
        return self;
    }
    
    /**
     * Sets the message instance to send.
     * @param message
     * @return
     */
    public T message(Message message) {
        StaticMessageContentBuilder staticMessageContentBuilder = StaticMessageContentBuilder.withMessage(message);
        staticMessageContentBuilder.setMessageHeaders(getMessageContentBuilder().getMessageHeaders());
        getAction().setMessageBuilder(staticMessageContentBuilder);
        return self;
    }

    /**
     * Sets the payload data on the message builder implementation.
     * @param payload
     * @return
     */
    protected void setPayload(String payload) {
        MessageContentBuilder messageContentBuilder = getMessageContentBuilder();

        if (messageContentBuilder instanceof PayloadTemplateMessageBuilder) {
            ((PayloadTemplateMessageBuilder) messageContentBuilder).setPayloadData(payload);
        } else if (messageContentBuilder instanceof StaticMessageContentBuilder) {
            ((StaticMessageContentBuilder) messageContentBuilder).getMessage().setPayload(payload);
        } else {
            throw new CitrusRuntimeException("Unable to set payload on message builder type: " + messageContentBuilder.getClass());
        }
    }

    /**
     * Sets the message name.
     * @param name
     * @return
     */
    public T name(String name) {
        getMessageContentBuilder().setMessageName(name);
        return self;
    }
    
    /**
     * Adds message payload data to this builder.
     * @param payload
     * @return
     */
    public T payload(String payload) {
        setPayload(payload);
        return self;
    }
    
    /**
     * Adds message payload resource to this builder.
     * @param payloadResource
     * @return
     */
    public T payload(Resource payloadResource) {
        try {
            setPayload(FileUtils.readToString(payloadResource));
        } catch (IOException e) {
            throw new CitrusRuntimeException("Failed to read payload resource", e);
        }
    
        return self;
    }

    /**
     * Sets payload POJO object which is marshalled to a character sequence using the given object to xml mapper.
     * @param payload
     * @param marshaller
     * @return
     */
    public T payload(Object payload, Marshaller marshaller) {
        StringResult result = new StringResult();
        
        try {
            marshaller.marshal(payload, result);
        } catch (XmlMappingException e) {
            throw new CitrusRuntimeException("Failed to marshal object graph for message payload", e);
        } catch (IOException e) {
            throw new CitrusRuntimeException("Failed to marshal object graph for message payload", e);
        }
        
        setPayload(result.toString());
        return self;
    }

    /**
     * Sets payload POJO object which is mapped to a character sequence using the given object to json mapper.
     * @param payload
     * @param objectMapper
     * @return
     */
    public T payload(Object payload, ObjectMapper objectMapper) {
        try {
            setPayload(objectMapper.writer().writeValueAsString(payload));
        } catch (JsonProcessingException e) {
            throw new CitrusRuntimeException("Failed to map object graph for message payload", e);
        }

        return self;
    }

    /**
     * Sets payload POJO object which is marshalled to a character sequence using the default object to xml or object
     * to json mapper that is available in Spring bean application context.
     *
     * @param payload
     * @return
     */
    public T payloadModel(Object payload) {
        Assert.notNull(applicationContext, "Citrus application context is not initialized!");

        if (!CollectionUtils.isEmpty(applicationContext.getBeansOfType(Marshaller.class))) {
            return payload(payload, applicationContext.getBean(Marshaller.class));
        } else if (!CollectionUtils.isEmpty(applicationContext.getBeansOfType(ObjectMapper.class))) {
            return payload(payload, applicationContext.getBean(ObjectMapper.class));
        }

        throw new CitrusRuntimeException("Unable to find default object mapper or marshaller in application context");
    }

    /**
     * Sets payload POJO object which is marshalled to a character sequence using the given object to xml mapper that
     * is accessed by its bean name in Spring bean application context.
     *
     * @param payload
     * @param mapperName
     * @return
     */
    public T payload(Object payload, String mapperName) {
        Assert.notNull(applicationContext, "Citrus application context is not initialized!");

        if (applicationContext.containsBean(mapperName)) {
            Object mapper = applicationContext.getBean(mapperName);

            if (Marshaller.class.isAssignableFrom(mapper.getClass())) {
                return payload(payload, (Marshaller) mapper);
            } else if (ObjectMapper.class.isAssignableFrom(mapper.getClass())) {
                return payload(payload, (ObjectMapper) mapper);
            } else {
                throw new CitrusRuntimeException(String.format("Invalid bean type for mapper '%s' expected ObjectMapper or Marshaller but was '%s'", mapperName, mapper.getClass()));
            }
        }

        throw new CitrusRuntimeException("Unable to find default object mapper or marshaller in application context");
    }

    /**
     * Adds message header name value pair to this builder's message sending action.
     * @param name
     * @param value
     */
    public T header(String name, Object value) {
        getMessageContentBuilder().getMessageHeaders().put(name, value);
        return self;
    }

    /**
     * Adds message header data to this builder's message sending action. Message header data is used in SOAP
     * messages for instance as header XML fragment.
     * @param data
     */
    public T header(String data) {
        getMessageContentBuilder().getHeaderData().add(data);
        return self;
    }

    /**
     * Adds message header data as file resource to this builder's message sending action. Message header data is used in SOAP
     * messages for instance as header XML fragment.
     * @param resource
     */
    public T header(Resource resource) {
        try {
            getMessageContentBuilder().getHeaderData().add(FileUtils.readToString(resource));
        } catch (IOException e) {
            throw new CitrusRuntimeException("Failed to read header resource", e);
        }
        return self;
    }

    /**
     * Sets a explicit message type for this receive action.
     * @param messageType
     * @return
     */
    public T messageType(MessageType messageType) {
        messageType(messageType.name());
        return self;
    }

    /**
     * Sets a explicit message type for this receive action.
     * @param messageType
     * @return
     */
    public T messageType(String messageType) {
        this.messageType = messageType;
        getAction().setMessageType(messageType);
        return self;
    }

    /**
     * Get message builder, if already registered or create a new message builder and register it
     *
     * @return the message builder in use
     */
    protected AbstractMessageContentBuilder getMessageContentBuilder() {
        if (getAction().getMessageBuilder() != null && getAction().getMessageBuilder() instanceof AbstractMessageContentBuilder) {
            return (AbstractMessageContentBuilder) getAction().getMessageBuilder();
        } else {
            PayloadTemplateMessageBuilder messageBuilder = new PayloadTemplateMessageBuilder();
            getAction().setMessageBuilder(messageBuilder);
            return messageBuilder;
        }
    }

    /**
     * Extract message header entry as variable before message is sent.
     * @param headerName
     * @param variable
     * @return
     */
    public T extractFromHeader(String headerName, String variable) {
        if (headerExtractor == null) {
            headerExtractor = new MessageHeaderVariableExtractor();

            getAction().getVariableExtractors().add(headerExtractor);
        }
        
        headerExtractor.getHeaderMappings().put(headerName, variable);
        return self;
    }
    
    /**
     * Extract message element via XPath or JSONPath from payload before message is sent.
     * @param path
     * @param variable
     * @return
     */
    public T extractFromPayload(String path, String variable) {
        if (JsonPathMessageValidationContext.isJsonPathExpression(path)) {
            getJsonPathVariableExtractor().getJsonPathExpressions().put(path, variable);
        } else {
            getXpathVariableExtractor().getXpathExpressions().put(path, variable);
        }
        return self;
    }

    /**
     * Adds XPath manipulating expression that evaluates to message payload before sending.
     * @param expression
     * @param value
     * @return
     */
    public T xpath(String expression, String value) {
        if (xpathMessageConstructionInterceptor == null) {
            xpathMessageConstructionInterceptor = new XpathMessageConstructionInterceptor();

            if (getAction().getMessageBuilder() != null) {
                (getAction().getMessageBuilder()).add(xpathMessageConstructionInterceptor);
            } else {
                PayloadTemplateMessageBuilder messageBuilder = new PayloadTemplateMessageBuilder();
                messageBuilder.getMessageInterceptors().add(xpathMessageConstructionInterceptor);

                getAction().setMessageBuilder(messageBuilder);
            }
        }

        xpathMessageConstructionInterceptor.getXPathExpressions().put(expression, value);
        return self;
    }

    /**
     * Adds JSONPath manipulating expression that evaluates to message payload before sending.
     * @param expression
     * @param value
     * @return
     */
    public T jsonPath(String expression, String value) {
        if (jsonPathMessageConstructionInterceptor == null) {
            jsonPathMessageConstructionInterceptor = new JsonPathMessageConstructionInterceptor();

            if (getAction().getMessageBuilder() != null) {
                (getAction().getMessageBuilder()).add(jsonPathMessageConstructionInterceptor);
            } else {
                PayloadTemplateMessageBuilder messageBuilder = new PayloadTemplateMessageBuilder();
                messageBuilder.getMessageInterceptors().add(jsonPathMessageConstructionInterceptor);

                getAction().setMessageBuilder(messageBuilder);
            }
        }

        jsonPathMessageConstructionInterceptor.getJsonPathExpressions().put(expression, value);
        return self;
    }

    /**
     * Creates new variable extractor and adds it to test action.
     */
    private XpathPayloadVariableExtractor getXpathVariableExtractor() {
        if (xpathExtractor == null) {
            xpathExtractor = new XpathPayloadVariableExtractor();

            getAction().getVariableExtractors().add(xpathExtractor);
        }

        return xpathExtractor;
    }

    /**
     * Creates new variable extractor and adds it to test action.
     */
    private JsonPathVariableExtractor getJsonPathVariableExtractor() {
        if (jsonPathExtractor == null) {
            jsonPathExtractor = new JsonPathVariableExtractor();

            getAction().getVariableExtractors().add(jsonPathExtractor);
        }

        return jsonPathExtractor;
    }

    /**
     * Sets the Spring bean application context.
     * @param applicationContext
     */
    public T withApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        return self;
    }

    /**
     * Sets explicit data dictionary for this receive action.
     * @param dictionary
     * @return
     */
    public T dictionary(DataDictionary dictionary) {
        getAction().setDataDictionary(dictionary);
        return self;
    }

    /**
     * Sets explicit data dictionary by name.
     * @param dictionaryName
     * @return
     */
    @SuppressWarnings("unchecked")
    public T dictionary(String dictionaryName) {
        Assert.notNull(applicationContext, "Citrus application context is not initialized!");
        DataDictionary dictionary = applicationContext.getBean(dictionaryName, DataDictionary.class);

        getAction().setDataDictionary(dictionary);
        return self;
    }

    /**
     * Provides access to receive message action delegate.
     * @return
     */
    protected SendMessageAction getAction() {
        return (SendMessageAction) action.getDelegate();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy