IHMParamTemplateClass.php 8.47 KB
<?php

/**
 * @class IHMParamTemplateClass
 * @brief Class used to manage templated parameters
 * @details
 */
class IHMParamTemplateClass
{
	protected $paramTemplateList = null;
	protected $paramTemplateListFilePath;
	
	protected static $paramTemplateNode                    = 'paramTemplate';
	protected static $paramTemplateIdAtt                   = 'paramId';
	protected static $paramTemplateFileNameAtt             = 'fileName';
	protected static $paramTemplateArgumentsNode           = 'arguments';
	protected static $paramTemplateArgumentNode            = 'argument';
	protected static $paramTemplateArgumentKeyAtt          = 'key';
	protected static $paramTemplateArgumentNameAtt         = 'name';
	protected static $paramTemplateArgumentTypeAtt         = 'type';
	protected static $paramTemplateArgumentDefaultAtt      = 'default';
	protected static $paramTemplateArgumentListItemNode    = 'item';
	protected static $paramTemplateArgumentListItemKeyAtt  = 'key';
	protected static $paramTemplateArgumentListItemNameAtt = 'name';
	
	/*
	 * @brief Constructor
	*/
	function __construct()
	{
		$this->paramTemplateListFilePath = IHMConfigClass::getParamTemplateListFilePath();
	}
	
	/*
	 * @brief Get list of templated parameters
	 */
	public function getParamTemplates() {
		$this->loadUserParamManagerFile();
		return $this->paramTemplateList;
	}
	
	/*
	 * @brief Check if param_id is a templated parameter
	*/
	public function isTemplatedParam($param_id) {
		$list = $this->getParamTemplates();
		return array_key_exists($param_id, $list);
	}
	
	/*
	 * 
	 */
	public function parseTemplatedParam($param_expression) {
		$exploded_param_expression = explode('_',$param_expression);
		
		$tmp_paramid = "";
		$real_param_id = "";
		
		foreach ($exploded_param_expression as $expression_part) {
			//add one by one each part of the expression to check if it's a templated parameter
			if ($tmp_paramid != "")
				$tmp_paramid .= "_";
			$tmp_paramid .= $expression_part;
			if ($this->isTemplatedParam($tmp_paramid)) {
				$real_param_id = $tmp_paramid;
				break;
			}
		}
		
		if (empty($real_param_id))
			return FALSE;
		
		$template_args_str = str_replace($real_param_id, "", $param_expression);
		
		if ($template_args_str == "")
			//A templated param need at least one argument
			return FALSE;
		
		$template_args_info = $this->paramTemplateList[$real_param_id];
		
		$args_format = "";
		foreach ($template_args_info["arguments"] as $arg) {
			$args_format .= "_";
			switch($arg["type"]) {
				case 'float' :
				case 'double' :
					$args_format .= "%f";
					break;
				case 'int' :
				case 'bool' :
					$args_format .= "%d";
					break;
				default:
					$args_format .= "%s";
			}
		}
		
		$exploded_args = sscanf($template_args_str , $args_format);
		
		if ($exploded_args === -1)
			return FALSE;
		
		$template_args = array();
		$i = 0;
		foreach ($template_args_info["arguments"] as $arg_key => $arg) {
			$template_args[$arg_key] = $exploded_args[$i];
			++$i;
		}
		
		return array(
			"paramid"       => $real_param_id,
			"fullparamid" => $param_expression,
			"template_args" => $template_args
		);
	}
	
	/*
	 * @brief Get templated parameter id
	*/
	public function getTemplatedParamId($param_id, $template_args) {
		$templatePath = $this->getTemplatePath($param_id);
		
		if (empty($templatePath))
			return "";
		
		if (!isset($template_args))
			$template_args = array();
		
		//Enrich template args with default values
		$this->addDefaultValues($param_id, $template_args);
		
		return basename($this->replaceArgs($templatePath, $template_args), ".xml");
	}
	
	/*
	 * @brief Generate parameter file from template
	 */
	public function generateTemplatedParamFile($param_id, $template_args) {
		$templatePath = $this->getTemplatePath($param_id);
		if (empty($templatePath))
			return "";
		
		if (!isset($template_args))
			$template_args = array();
		
		//Enrich template args with default values
		$this->addDefaultValues($param_id, $template_args);
		
		$dst_param_id = $this->getTemplatedParamId($param_id, $template_args);
			
		//Build destination file path
		$dstDir = IHMConfigClass::getTemplateParamGeneratePath();
		if (!is_dir($dstDir))
			mkdir($dstDir);		
		$dstFilePath = $dstDir."/".$dst_param_id.".xml";
		
		//Check if it's necessary to generate the parameter file
		if (file_exists($dstFilePath)) {
			$dateModifDst = filemtime($dstFilePath);
			$dateModifTemplate = filemtime($templatePath);
			
			if ($dateModifTemplate != $dateModifDst)
				//no modification - reuse old generated file
				return $dstFilePath;
		}
		
		//Generate file
		$templateHandle = fopen($templatePath, "r");
		$dstHandle = fopen($dstFilePath, "w");
		if (!$templateHandle || !$dstHandle)
			return "";
		while (($line = fgets($templateHandle)) !== false) {
			fwrite($dstHandle, $this->replaceArgs($line, $template_args));
		}
		fclose($templateHandle);
		fclose($dstHandle);
		
		$dateModifTemplate = filemtime($templatePath);
		touch($dstFilePath, $dateModifTemplate);
		
		return $dstFilePath;
	}
	
	/*
	 * @brief Get template file path
	 */
	public function getTemplatePath($param_id) {
		if (!$this->isTemplatedParam($param_id))
			return "";
		return IHMConfigClass::getParamTemplateFilePath($this->paramTemplateList[$param_id]['fileName']);
	}
	
	/*
	 * 
	 */
	public function getTemplateFileName($param_id) {
		if (!$this->isTemplatedParam($param_id))
			return "";
		return $this->paramTemplateList[$param_id]['fileName'];
	}
	
	/*
	 * @brief Replace args in string
	*/
	private function replaceArgs($string, $template_args) {
		$result = $string;
		foreach ($template_args as $template_arg_key => $template_arg_value) {
			$result = str_replace("##".$template_arg_key."##", $template_arg_value, $result);
		}
		return $result;
	}
	
	/*
	 * @brief Enrich Template args with default values
	 */
	private function addDefaultValues($param_id, &$template_args) {
		$list = $this->getParamTemplates();
		
		if (!array_key_exists($param_id, $list))
			return;
		
		$arguments = $list[$param_id]->arguments;
		foreach ($arguments as $arg_key => $arg_def) {
			if (!array_key_exists($arg_key, $template_args))
				$template_args[$arg_key] = $arg_def->default;
		}
	}
	
	/*
	 * @brief Load list of templated parameters
	*/
	protected function loadUserParamManagerFile()
	{
		if (isset($this->paramTemplateList))
			return;
		
		$this->paramTemplateList = array();
	 
		//load xml file
		$dom = new DomDocument("1.0");
		if (!$dom->load($this->paramTemplateListFilePath))
			return;
			
		$paramTemplateNodes = $dom->getElementsByTagName(self::$paramTemplateNode);

		foreach ($paramTemplateNodes as $paramTemplateNode) {
			$paramId       = $paramTemplateNode->getAttribute(self::$paramTemplateIdAtt);
			$paramFileName = $paramTemplateNode->getAttribute(self::$paramTemplateFileNameAtt);
			
			if (empty($paramId) || empty($paramFileName))
				continue;
				
			$arguments = array();
			
			$argumentsNode = $paramTemplateNode->getElementsByTagName(self::$paramTemplateArgumentsNode);
			
			if (count($argumentsNode) > 0) {
				$argumentsNode = $argumentsNode->item(0);
				$argumentNodes = $argumentsNode->getElementsByTagName(self::$paramTemplateArgumentNode);
				
				foreach($argumentNodes as $argumentNode) {
					$argumentKey  = $argumentNode->getAttribute(self::$paramTemplateArgumentKeyAtt);
					$argumentName = $argumentNode->getAttribute(self::$paramTemplateArgumentNameAtt);
					$argumentType = $argumentNode->getAttribute(self::$paramTemplateArgumentTypeAtt);
					$argumentDefault = $argumentNode->getAttribute(self::$paramTemplateArgumentDefaultAtt);
					
					if (empty($argumentKey) || empty($argumentType))
						continue;
					
					$arguments[$argumentKey] = array(
						"name" => (empty($argumentName) ? $argumentKey : $argumentName),
						"type" => $argumentType,
						"default" => $argumentDefault
					);
					
					switch ($argumentType) {
						case "list" :
							$arguments[$argumentKey]['items'] = array();
							
							$itemNodes = $argumentNode->getElementsByTagName(self::$paramTemplateArgumentListItemNode);
							foreach ($itemNodes as $itemNode) {
								$itemKey  = $itemNode->getAttribute(self::$paramTemplateArgumentListItemKeyAtt);
								$itemName = $itemNode->getAttribute(self::$paramTemplateArgumentListItemNameAtt);
								if ($itemKey == "")
									continue;
								$arguments[$argumentKey]['items'][$itemKey] = (empty($itemName) ? $itemKey : $itemName);
							}
							
							break;
						default:
							//Nothing to do
					}
				}
			}
			
			$this->paramTemplateList[$paramId] = array(
				"fileName"  => $paramFileName,
				"arguments" => $arguments
			);
			
		}
	}
}