IHMParamTemplateClass.php 11.9 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 $paramTemplateArgumentSubTypeAtt      = 'subtype';
	protected static $paramTemplateArgumentMinKeyAtt       = 'minkey';
	protected static $paramTemplateArgumentMaxKeyAtt       = 'maxkey';
	protected static $paramTemplateArgumentNameTplAtt      = 'nametpl';
	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;
				case 'list' :
					switch($arg["subtype"]) {
						case 'float' :
						case 'double' :
							$args_format .= "%f";
							break;
						case 'int' :
						case 'bool' :
							$args_format .= "%d";
							break;
						default:
							$args_format .= "%s";
					}
					break;
				default:
					$args_format .= "%s";
			}
		}
		
		$exploded_args = sscanf($template_args_str , $args_format);
		error_log($exploded_args);
		
		if ($exploded_args === -1)
			return FALSE;
		
		$template_args = array();
		$i = 0;
		foreach ($template_args_info["arguments"] as $arg_key => $arg) {
			if ($arg["type"] == "list") {
				if (!array_key_exists($exploded_args[$i], $arg['items'])) {
					return FALSE;
				}
			}
			$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, $table_link = NULL) {
		$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, $this->getArguments($param_id)));
		}
		fclose($templateHandle);
		fclose($dstHandle);

		if (isset($table_link)) {
			//Inject table link
			$xml = new DOMDocument();
			$xml->preserveWhiteSpace = TRUE;
			$xml->load($dstFilePath);

			$infoNodes = $xml->documentElement->getElementsByTagName('info');
			if ($infoNodes->length == 0) {
				$infoNode = $xml->createElement('info');
				$infoNode = $xml->documentElement->insertBefore($infoNode, $xml->documentElement->firstChild);
			}
			else {
				$infoNode = $infoNodes->item(0);
			}
		
			$tableNodes = $infoNode->getElementsByTagName('table');
			if ($tableNodes->length == 0) {
				$tableNode = $xml->createElement('table');
				$tableNode = $infoNode->appendChild($tableNode);
			}
			else {
				$tableNode = $tableNodes->item(0);
			}

			$linkTableNode = $xml->createElement('linkTable');
			$linkTableNode->setAttribute('originParamId', $table_link['paramid']);
			$linkTableNode->setAttribute('originTableDim', $table_link['relateddim']);
			$tableNode->appendChild($linkTableNode);

			$xml->save($dstFilePath);
		}
		
		$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']);
	}

	/*
	 *  @brief Get template id by template file name
	 */
	public function getTemplateId($template_name) {
		$list = $this->getParamTemplates();
		foreach ($list as $param_id => $param_info) {
			if ($param_info['fileName'] == $template_name) {
				return $param_id;
			}
		}
		return FALSE;
	}
	
	/*
	 * 
	 */
	public function getTemplateFileName($param_id) {
		if (!$this->isTemplatedParam($param_id))
			return "";
		return $this->paramTemplateList[$param_id]['fileName'];
	}
	
	/*
	 * @brief Replace args in string
	*/
	public function replaceArgs($string, $template_args, $arguments = array()) {
		$result = $string;
		if (empty($template_args)) {
			return $result;
		}
		foreach ($template_args as $template_arg_key => $template_arg_value) {
			$result = str_replace("##".$template_arg_key."##", $template_arg_value, $result);
			if (array_key_exists($template_arg_key, $arguments) && ($arguments[$template_arg_key]['type'] == 'list')) {
				$item_name = array_key_exists($template_arg_value, $arguments[$template_arg_key]['items']) ? $arguments[$template_arg_key]['items'][$template_arg_value] : 'Unknown';
				$result = str_replace("@@".$template_arg_key."@@", $item_name, $result);
			}
		}
		return $result;
	}
	
	/*
	 * @brief Enrich Template args with default values
	 */
	private function addDefaultValues($param_id, &$template_args) {
		$arguments = $this->getArguments($param_id);
		if (empty($arguments))
			return;
		foreach ($arguments as $arg_key => $arg_def) {
			if (!array_key_exists($arg_key, $template_args))
				$template_args[$arg_key] = $arg_def['default'];
		}
	}

	/*
	 * @brief Get list of arguments for a given parameter
	 */
	protected function getArguments($param_id) {
		$list = $this->getParamTemplates();

		if (!array_key_exists($param_id, $list) || !isset($list[$param_id]['arguments']))
			return array();
		return $list[$param_id]['arguments'];
	}
	
	/*
	 * @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);
					$argumentSubType = $argumentNode->getAttribute(self::$paramTemplateArgumentSubTypeAtt);
					$argumentDefault = $argumentNode->getAttribute(self::$paramTemplateArgumentDefaultAtt);
					$argumentMinKey = $argumentNode->getAttribute(self::$paramTemplateArgumentMinKeyAtt);
					$argumentMaxKey = $argumentNode->getAttribute(self::$paramTemplateArgumentMaxKeyAtt);
					$argumentNameTpl = $argumentNode->getAttribute(self::$paramTemplateArgumentNameTplAtt);
					
					if (empty($argumentKey) || empty($argumentType))
						continue;
					
					$arguments[$argumentKey] = array(
						"name" => (empty($argumentName) ? $argumentKey : $argumentName),
						"type" => $argumentType,
						"subtype" => $argumentSubType,
						"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;
						case "generated-list":
							$arguments[$argumentKey]['type'] = 'list';
							$arguments[$argumentKey]['items'] = array();
							for ($key = intval($argumentMinKey) ; $key <= intval($argumentMaxKey); ++$key) {
								$itemName = str_replace('##key##',$key,$argumentNameTpl);
								$arguments[$argumentKey]['items'][strval($key)] = $itemName;
							}
							break;
						default:
							//Nothing to do
					}
				}
			}
			
			$this->paramTemplateList[$paramId] = array(
				"fileName"  => $paramFileName,
				"arguments" => $arguments
			);
			
		}
	}
}