/*
 * 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 <axiom_xpath.h>
#include "xpath_streaming.h"
#include "xpath_internals.h"
#include "xpath_internals_engine.h"

axiom_xpath_streaming_t
axiom_xpath_streaming_check_operation(
    const axutil_env_t *env,
    axiom_xpath_expression_t* expr,
    int op_p)
{
    axiom_xpath_operation_t *op;

    if(op_p == AXIOM_XPATH_PARSE_END)
    {
        return AXIOM_XPATH_STREAMING_CONSTANT;
    }

    op = AXIOM_XPATH_OPR_EXPR_GET(op_p);

    switch(op->opr)
    {
        case AXIOM_XPATH_OPERATION_CONTEXT_NODE:
        case AXIOM_XPATH_OPERATION_ROOT_NODE:
            return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_STREAMING_CONSTANT);

        case AXIOM_XPATH_OPERATION_STEP:
            return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_CHECK(op->op2));

        case AXIOM_XPATH_OPERATION_RESULT:
            return AXIOM_XPATH_STREAMING_CONSTANT;

        case AXIOM_XPATH_OPERATION_UNION:
            return axiom_xpath_streaming_combine_independent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_CHECK(op->op2));

        case AXIOM_XPATH_OPERATION_EQUAL_EXPR:
            return axiom_xpath_streaming_combine_independent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_CHECK(op->op2));

        case AXIOM_XPATH_OPERATION_LITERAL:
            return AXIOM_XPATH_STREAMING_CONSTANT;

        case AXIOM_XPATH_OPERATION_NUMBER:
            return AXIOM_XPATH_STREAMING_CONSTANT;

        case AXIOM_XPATH_OPERATION_PATH_EXPRESSION:
            return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1),
                AXIOM_XPATH_CHECK(op->op2));

        case AXIOM_XPATH_OPERATION_NODE_TEST:
            return axiom_xpath_streaming_check_node_test(env, expr, op);

        case AXIOM_XPATH_OPERATION_PREDICATE:
            return axiom_xpath_streaming_check_predicate(env, expr, op_p);

        default:
			AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Unidentified operation.");

            return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }
}

axiom_xpath_streaming_t
axiom_xpath_streaming_check_predicate(
    const axutil_env_t *env,
    axiom_xpath_expression_t* expr,
    int op_p)
{
    axiom_xpath_operation_t *op;

    if(op_p == AXIOM_XPATH_PARSE_END)
    {
        return AXIOM_XPATH_STREAMING_CONSTANT;
    }

    op = AXIOM_XPATH_OPR_EXPR_GET(op_p);

    return axiom_xpath_streaming_combine_dependent(AXIOM_XPATH_CHECK(op->op1), AXIOM_XPATH_CHECK(
        op->op2));
}

axiom_xpath_streaming_t
axiom_xpath_streaming_check_node_test(
    const axutil_env_t *env,
    axiom_xpath_expression_t* expr,
    axiom_xpath_operation_t *op)
{
    axiom_xpath_axis_t axis = AXIOM_XPATH_AXIS_NONE;
    axiom_xpath_streaming_t r;

    if(!op->par2)
    {
		AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "axis is NULL in the step operator");
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }

    axis = *((axiom_xpath_axis_t *)op->par2);

    switch(axis)
    {
        case AXIOM_XPATH_AXIS_ATTRIBUTE:
        case AXIOM_XPATH_AXIS_CHILD:
            break;

        default:
            return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }

    r = axiom_xpath_streaming_check_predicate(env, expr, op->op1);

    if(r != AXIOM_XPATH_STREAMING_ATTRIBUTE && r != AXIOM_XPATH_STREAMING_CONSTANT)
    {
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }

    if(axis == AXIOM_XPATH_AXIS_ATTRIBUTE)
    {
        return AXIOM_XPATH_STREAMING_ATTRIBUTE;
    }
    else
    {
        return AXIOM_XPATH_STREAMING_SUPPORTED;
    }
}

axiom_xpath_streaming_t
axiom_xpath_streaming_combine_dependent(
    axiom_xpath_streaming_t r1,
    axiom_xpath_streaming_t r2)
{
    if(r1 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED)
    {
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }
    else if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED)
    {
        return AXIOM_XPATH_STREAMING_SUPPORTED;
    }
    else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE)
    {
        return AXIOM_XPATH_STREAMING_ATTRIBUTE;
    }
    else
    {
        return AXIOM_XPATH_STREAMING_CONSTANT;
    }
}

axiom_xpath_streaming_t
axiom_xpath_streaming_combine_independent(
    axiom_xpath_streaming_t r1,
    axiom_xpath_streaming_t r2)
{
    if(r1 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_NOT_SUPPORTED)
    {
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }
    else if(r1 == AXIOM_XPATH_STREAMING_CONSTANT || r2 == AXIOM_XPATH_STREAMING_CONSTANT)
    {
        if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED)
        {
            return AXIOM_XPATH_STREAMING_SUPPORTED;
        }
        else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE)
        {
            return AXIOM_XPATH_STREAMING_ATTRIBUTE;
        }
        else
        {
            return AXIOM_XPATH_STREAMING_CONSTANT;
        }
    }
    else if(r1 == AXIOM_XPATH_STREAMING_ATTRIBUTE || r2 == AXIOM_XPATH_STREAMING_ATTRIBUTE)
    {
        if(r1 == AXIOM_XPATH_STREAMING_SUPPORTED || r2 == AXIOM_XPATH_STREAMING_SUPPORTED)
        {
            return AXIOM_XPATH_STREAMING_SUPPORTED;
        }
        else
        {
            return AXIOM_XPATH_STREAMING_ATTRIBUTE;
        }
    }
    else
    {
        return AXIOM_XPATH_STREAMING_NOT_SUPPORTED;
    }
}

