
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

#include <axis2_flow.h>
#include <axis2_flow_container.h>

struct axis2_flow_container
{
    axis2_flow_t *in;
    axis2_flow_t *out;
    axis2_flow_t *in_fault;
    axis2_flow_t *out_fault;
};

AXIS2_EXTERN axis2_flow_container_t *AXIS2_CALL
axis2_flow_container_create(
    const axutil_env_t * env)
{
    axis2_flow_container_t *flow_container = NULL;

    flow_container = (axis2_flow_container_t *) AXIS2_MALLOC(env->
                                                             allocator,
                                                             sizeof
                                                             (axis2_flow_container_t));

    if (!flow_container)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        return NULL;
    }

    flow_container->in = NULL;
    flow_container->out = NULL;
    flow_container->in_fault = NULL;
    flow_container->out_fault = NULL;

    return flow_container;
}

AXIS2_EXTERN void AXIS2_CALL
axis2_flow_container_free(
    axis2_flow_container_t * flow_container,
    const axutil_env_t * env)
{
    if (flow_container->in)
    {
        axis2_flow_free(flow_container->in, env);
    }

    if (flow_container->out)
    {
        axis2_flow_free(flow_container->out, env);
    }

    if (flow_container->in_fault)
    {
        axis2_flow_free(flow_container->in_fault, env);
    }

    if (flow_container->out_fault)
    {
        axis2_flow_free(flow_container->out_fault, env);
    }

    if (flow_container)
    {
        AXIS2_FREE(env->allocator, flow_container);
    }

    return;
}

AXIS2_EXTERN axis2_flow_t *AXIS2_CALL
axis2_flow_container_get_in_flow(
    const axis2_flow_container_t * flow_container,
    const axutil_env_t * env)
{
    return flow_container->in;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_flow_container_set_in_flow(
    axis2_flow_container_t * flow_container,
    const axutil_env_t * env,
    axis2_flow_t * in_flow)
{
    if (flow_container->in)
    {
        axis2_flow_free(flow_container->in, env);
    }
    flow_container->in = in_flow;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_flow_t *AXIS2_CALL
axis2_flow_container_get_out_flow(
    const axis2_flow_container_t * flow_container,
    const axutil_env_t * env)
{
    return flow_container->out;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_flow_container_set_out_flow(
    axis2_flow_container_t * flow_container,
    const axutil_env_t * env,
    axis2_flow_t * out_flow)
{
    if (flow_container->out)
    {
        axis2_flow_free(flow_container->out, env);
    }
    flow_container->out = out_flow;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_flow_t *AXIS2_CALL
axis2_flow_container_get_fault_in_flow(
    const axis2_flow_container_t * flow_container,
    const axutil_env_t * env)
{
    return flow_container->in_fault;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_flow_container_set_fault_in_flow(
    axis2_flow_container_t * flow_container,
    const axutil_env_t * env,
    axis2_flow_t * falut_in_flow)
{
    if (flow_container->in_fault)
    {
        axis2_flow_free(flow_container->in_fault, env);
    }
    flow_container->in_fault = falut_in_flow;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_flow_t *AXIS2_CALL
axis2_flow_container_get_fault_out_flow(
    const axis2_flow_container_t * flow_container,
    const axutil_env_t * env)
{
    return flow_container->out_fault;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axis2_flow_container_set_fault_out_flow(
    axis2_flow_container_t * flow_container,
    const axutil_env_t * env,
    axis2_flow_t * fault_out_flow)
{
    AXIS2_PARAM_CHECK(env->error, fault_out_flow, AXIS2_FAILURE);
    if (flow_container->out_fault)
    {
        axis2_flow_free(flow_container->out_fault, env);
    }
    flow_container->out_fault = fault_out_flow;
    return AXIS2_SUCCESS;
}

