<?php
/**
 * This file is part of the transcoding library. It contains the
 * definition of the {@link Transcoder} class.
 * 
 * @author Sylvain Lequeux
 * @author Francois Daoust <fd@w3.org>
 * @package TransPythia
 * @version $Revision: 1.14 $
 * @license http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html W3C Software Notice and License
 * @copyright Copyright (c) 2009, W3C (MIT, ERCIM, Keio)
 */

/**
 * Include the {@link ServiceFactory} class description.
 */
require_once(dirname(__FILE__) . '/../ddrsimpleapi/interface/serviceFactory.php');
/**
 * Include the {@link SystemException} class description.
 */
require_once(dirname(__FILE__) . '/../ddrsimpleapi/interface/systemException.php');


/**
 * A Transcoder applies transcoding actions (see {@link TranscodingAction})
 * to content, based on the capabilities of the device that requested the
 * content.
 * 
 * Although the class is pretty generic, the goal of the transcoder within
 * the transcoding library is to transform content that is not suitable for
 * requesting device to content that will provide at least a functional user
 * experience on that device.
 * 
 * The capabilities of the requesting device are retrieved from a device
 * description repository (DDR), accessed through the DDR Simple API. The
 * transcoder provides a {@link Service} and an {@link Evidence} to the
 * underlying transcoding actions so that they may react consequently.
 *
 * @author Sylvain Lequeux
 * @author Francois Daoust <fd@w3.org>
 * @package TransPythia
 * @version $Revision: 1.14 $
 * @license http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html W3C Software Notice and License
 * @copyright Copyright (c) 2009, W3C (MIT, ERCIM, Keio)
 */
class Transcoder {
	/**
	 * @var array(TranscodingAction) The list of TranscodingAction to apply.
	 */
	private $transcodingActions;
	/**
	 * @var Service The DDR service to use to retrieve the capabilities of
	 *              the requesting device.
	 */
	private $service;
	
	/**
	 * Creates an empty transcoder associated with a DDR service.
	 * 
	 * The transcoding actions that the transcoder needs to apply to content
	 * should be added through one or more calls to
	 * {@link addTranscodingAction()}.
	 * 
	 * @param Service $service The DDR service to use to retrieve the
	 *                         capabilities of the requesting device.
	 * @return A new empty transcoder.
	 * @exception SystemException The given service is invalid.
	 */
	public function __construct($service){
		if(!isset($service)){
			throw new SystemException(
				'The DDR service cannot be null.',
				SystemException::$ILLEGAL_ARGUMENT);
		}
		if(!($service instanceof Service)){
			throw new SystemException(
				'The DDR service does not implement the Service interface.',
				SystemException::$ILLEGAL_ARGUMENT);
		}
		
		$this->service = $service;
		$this->transcodingActions = array();
	}
	
	/**
	 * Factory method that creates a transcoding action from the given name
	 * that will use the transcoder's DDR service to resolve the requesting
	 * device's capabilities.
	 * 
	 * Please note that the created transcoding action is not automatically
	 * added to the transcoder. A subsequent call to {@link addTranscodingAction()}
	 * is required for that to happen.
	 * 
	 * @param string $actionName The name of the transcoding action class.
	 *                           The method will try to include the file
	 *                           'transcodingaction' + $actionName + '.php'
	 *                           but will not fail if it does not exist.
	 * @return TranscodingAction A new instance of the requested transcoding
	 *                           action.
	 * @exception SystemException The transcoding action could not be created.
	 */
	public function newTranscodingAction($actionName){
		try{
			$filename = dirname(__FILE__) . '/transcodingaction' . strtolower($actionName) . '.php';
			if (file_exists($filename)) {
				include_once($filename);			
			}
		
			$class = 'TranscodingAction' . $actionName;
			$action = new $class($this->service);
			return $action;
		}
		catch(Exception $e){
			throw new SystemException(
				'The transcoding action ' . $actionName . ' could not be created.',
				SystemException::$CANNOT_PROCEED,
				$e);
		}
	}
	
	/**
	 * Adds a transcoding action to the set.
	 * 
	 * @param TranscodingAction $action The transcoding action to add to the list.
	 * @exception SystemException The transcoding action is not valid.
	 */
	public function addTranscodingAction($action){
		if(!isset($action)){
			throw new SystemException(
				'The action cannot be null.',
				SystemException::$ILLEGAL_ARGUMENT);
		}
		if(!($action instanceof TranscodingAction)){
			throw new SystemException(
				'The DDR service does not subclass TranscodingAction.',
				SystemException::$ILLEGAL_ARGUMENT);
		}
		
		$this->transcodingActions[] = $action;
	}
	
	/**
	 * Applies all the transcoding actions to the given content, one at a turn,
	 * in the order in which they were added to the transcoder.
	 * 
	 * @param string $content The content to be modified.
	 * @param Evidence $evidence The evidence that identifies the requesting device.
	 * @return string The transcoded content.
	 * @exception SystemException The evidence is not valid.
	 */
	public function apply($content, $evidence){
		if(!isset($evidence)){
			throw new SystemException(
				'The evidence cannot be null.',
				SystemException::$ILLEGAL_ARGUMENT);
		}
		if(!($evidence instanceof Evidence)){
			throw new SystemException(
				'The evidence does not implement the Evidence interface.',
				SystemException::$ILLEGAL_ARGUMENT);
		}
		
		foreach($this->transcodingActions as $action){
			$content = $action->apply($content, $evidence);
		}
		return $content;
	}
}

?>