<?php
/**
 * File containing the ezcWorkflowNodeConditionalBranch class.
 *
 * 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.
 *
 * @package Workflow
 * @version //autogen//
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 */

/**
 * Abstract base class for nodes that conditionally branch multiple threads of
 * execution.
 *
 * Most implementations only need to set the conditions for proper functioning.
 *
 * @package Workflow
 * @version //autogen//
 */
abstract class ezcWorkflowNodeConditionalBranch extends ezcWorkflowNodeBranch
{
    /**
     * Constraint: The minimum number of conditional outgoing nodes this node
     * has to have. Set to false to disable this constraint.
     *
     * @var integer
     */
    protected $minConditionalOutNodes = false;

    /**
     * Constraint: The minimum number of conditional outgoing nodes this node
     * has to activate. Set to false to disable this constraint.
     *
     * @var integer
     */
    protected $minActivatedConditionalOutNodes = false;

    /**
     * Constraint: The maximum number of conditional outgoing nodes this node
     * may activate. Set to false to disable this constraint.
     *
     * @var integer
     */
    protected $maxActivatedConditionalOutNodes = false;

    /**
     * Holds the conditions of the out nodes.
     *
     * The key is the position of the out node in the array of out nodes.
     *
     * @var array( 'condition' => array( 'int' => ezcWorkflowCondtion ) )
     */
    protected $configuration = array(
      'condition' => array(),
      'else' => array()
    );

    /**
     * Adds the conditional outgoing node $outNode to this node with the
     * condition $condition. Optionally, an $else node can be specified that is
     * activated when the $condition evaluates to false.
     *
     * @param ezcWorkflowCondition $condition
     * @param ezcWorkflowNode      $outNode
     * @param ezcWorkflowNode      $else
     * @return ezcWorkflowNode
     */
    public function addConditionalOutNode( ezcWorkflowCondition $condition, ezcWorkflowNode $outNode, ezcWorkflowNode $else = null )
    {
        $this->addOutNode( $outNode );
        $this->configuration['condition'][ezcWorkflowUtil::findObject( $this->outNodes, $outNode )] = $condition;

        if ( !is_null( $else ) )
        {
            $this->addOutNode( $else );

            $key = ezcWorkflowUtil::findObject( $this->outNodes, $else );
            $this->configuration['condition'][$key] = new ezcWorkflowConditionNot( $condition );
            $this->configuration['else'][$key] = true;
        }

        return $this;
    }

    /**
     * Returns the condition for a conditional outgoing node
     * and false if the passed not is not a (unconditional)
     * outgoing node of this node.
     *
     * @param  ezcWorkflowNode $node
     * @return ezcWorkflowCondition
     * @ignore
     */
    public function getCondition( ezcWorkflowNode $node )
    {
        $keys    = array_keys( $this->outNodes );
        $numKeys = count( $keys );

        for ( $i = 0; $i < $numKeys; $i++ )
        {
            if ( $this->outNodes[$keys[$i]] === $node )
            {
                if ( isset( $this->configuration['condition'][$keys[$i]] ) )
                {
                    return $this->configuration['condition'][$keys[$i]];
                }
                else
                {
                    return false;
                }
            }
        }

        return false;
    }

    /**
     * Returns true when the $node belongs to an ELSE condition.
     *
     * @param ezcWorkflowNode $node
     * @return bool
     * @ignore
     */
    public function isElse( ezcWorkflowNode $node )
    {
        return isset( $this->configuration['else'][ezcWorkflowUtil::findObject( $this->outNodes, $node )] );
    }

    /**
     * Evaluates all the conditions, checks the constraints and activates any nodes that have
     * passed through both checks and condition evaluation.
     *
     * @param ezcWorkflowExecution $execution
     * @return boolean true when the node finished execution,
     *                 and false otherwise
     * @ignore
     */
    public function execute( ezcWorkflowExecution $execution )
    {
        $keys                            = array_keys( $this->outNodes );
        $numKeys                         = count( $keys );
        $nodesToStart                    = array();
        $numActivatedConditionalOutNodes = 0;

        if ( $this->maxActivatedConditionalOutNodes !== false )
        {
            $maxActivatedConditionalOutNodes = $this->maxActivatedConditionalOutNodes;
        }
        else
        {
            $maxActivatedConditionalOutNodes = $numKeys;
        }

        for ( $i = 0; $i < $numKeys && $numActivatedConditionalOutNodes <= $maxActivatedConditionalOutNodes; $i++ )
        {
            if ( isset( $this->configuration['condition'][$keys[$i]] ) )
            {
                // Conditional outgoing node.
                if ( $this->configuration['condition'][$keys[$i]]->evaluate( $execution->getVariables() ) )
                {
                    $nodesToStart[] = $this->outNodes[$keys[$i]];
                    $numActivatedConditionalOutNodes++;
                }
            }
            else
            {
                // Unconditional outgoing node.
                $nodesToStart[] = $this->outNodes[$keys[$i]];
            }
        }

        if ( $this->minActivatedConditionalOutNodes !== false && $numActivatedConditionalOutNodes < $this->minActivatedConditionalOutNodes )
        {
            throw new ezcWorkflowExecutionException(
              'Node activates less conditional outgoing nodes than required.'
            );
        }

        return $this->activateOutgoingNodes( $execution, $nodesToStart );
    }

    /**
     * Checks this node's constraints.
     *
     * @throws ezcWorkflowInvalidWorkflowException if the constraints of this node are not met.
     */
    public function verify()
    {
        parent::verify();

        $numConditionalOutNodes = count( $this->configuration['condition'] );

        if ( $this->minConditionalOutNodes !== false && $numConditionalOutNodes < $this->minConditionalOutNodes )
        {
            throw new ezcWorkflowInvalidWorkflowException(
              'Node has less conditional outgoing nodes than required.'
            );
        }
    }
}
?>
