From ba9b1b7d6bad5ad4dbf8d5b8c38a8f04d166dc26 Mon Sep 17 00:00:00 2001
From: Benjamin Renard <benjamin.renard@akka.eu>
Date: Tue, 30 Jul 2019 16:12:53 +0200
Subject: [PATCH] Rework of TT and Catalog cache

---
 js/app/views/CatalogUI.js                    |   4 ++--
 php/classes/CatalogCacheIntervalObject.php   | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------
 php/classes/CatalogCacheMgr.php              | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------
 php/classes/CatalogCacheObject.php           | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------
 php/classes/CatalogMgr.php                   | 134 ++++++++++++++++++++++++++++++--------------------------------------------------------------------------------------------------------
 php/classes/TimeTableCacheIntervalObject.php |   4 +++-
 php/classes/TimeTableCacheMgr.php            |  16 +++++++++++-----
 php/classes/TimeTableCacheObject.php         |  34 ++++++++++++++++++++++++++--------
 php/classes/TimeTableMgr.php                 | 121 +++++--------------------------------------------------------------------------------------------------------------------
 9 files changed, 347 insertions(+), 497 deletions(-)

diff --git a/js/app/views/CatalogUI.js b/js/app/views/CatalogUI.js
index 2149517..ed970b0 100644
--- a/js/app/views/CatalogUI.js
+++ b/js/app/views/CatalogUI.js
@@ -333,12 +333,12 @@ Ext.define('amdaUI.CatalogUI', {
 
 			Ext.Array.each(result.parameters, function(obj, index) {
 				var field = {
-					name: 'param'+(index+2)
+					name: obj.id
 				};
 				var column = {
 					text: obj.name,
 					sortable : true,
-					dataIndex: 'param'+(index+2),
+					dataIndex: obj.id,
 					menuDisabled: false,
 					listeners: {
 						'sortchange' : function(ct, column, direction, eOpts) {
diff --git a/php/classes/CatalogCacheIntervalObject.php b/php/classes/CatalogCacheIntervalObject.php
index 18a6201..faeddd3 100644
--- a/php/classes/CatalogCacheIntervalObject.php
+++ b/php/classes/CatalogCacheIntervalObject.php
@@ -7,30 +7,19 @@ class CatalogCacheIntervalObject extends TimeTableCacheIntervalObject
 
 	public function toArray()
 	{
-		$result = array(
-			"cacheId" => $this->id,
-			"start"   => $this->getStartToISO(),
-			"stop"    => $this->getStopToISO()
-		);
-		if ($this->isNew)
-			$result["isNew"] = true;
-
-		if ($this->isModified)
-			$result["isModified"] = true;
-
-		for ($i = 0; $i < count($this->params); $i++)
+		$result = parent::toArray();
+
+		foreach ($this->cacheObject->getParametersInfo() as $parameter)
 		{
-			$paramObject = array();
-			$index = 'param'.sprintf("%d",$i+2);
-			$result[$index] = $this->params[$i];
+			$result[$parameter['id']] = $this->params[$parameter['id']];
 		}
 		return $result;
 	}
 
 	// for catalog
-	public function setParams($params)
+	public function setParamValue($param_id, $param_value)
 	{
-		$this->params = $params;
+		$this->params[$param_id] = $param_value;
 	}
 
 	public function getParams()
@@ -38,62 +27,113 @@ class CatalogCacheIntervalObject extends TimeTableCacheIntervalObject
 	   return $this->params;
 	}
 
-	public function writeBin($handle, $paramsNumber, $paramsSizes, $paramsTypes)
+	public function writeBin($handle)
 	{
-		fwrite($handle,pack('L6',$this->id,$this->index,$this->start,$this->stop,$this->isNew,$this->isModified));
-		for ($i = 0; $i < $paramsNumber; $i++)
+		parent::writeBin($handle);
+
+		foreach ($this->cacheObject->getParametersInfo() as $parameter)
 		{
-			if ($paramsTypes[$i] == '2') // string
-			{
-				fwrite($handle,pack('d', strlen($this->params[$i])));
-				fwrite($handle, $this->params[$i],strlen($this->params[$i]));
+			$size = $parameter['size'];
+			$values = $this->params[$parameter['id']];
+			if ($size > 1) {
+				$values_array = explode(',',$values);
+			}
+			else {
+				$values_array = array($values);
 			}
-			else
-			{
-				if ($paramsTypes[$i] == '1')
-						$paramString = TimeUtils::iso2stamp($this->params[$i]);
-				else
-						$paramString = $this->params[$i];
-
-				$paramArray =  explode(',',$paramString);
-				for ($j = 0; $j < $paramsSizes[$i]; $j++) fwrite($handle,pack('d', $paramArray[$j]));
+			for ($i = 0; $i < $size; ++$i) {
+				$value = ($i >= count($values_array)) ? "" : $values_array[$i];
+				switch ($parameter['type']) {
+					case 0: //double
+						fwrite($handle,pack('d', floatval($value)));
+					  break;
+					case 1: //date (timestamp)
+						fwrite($handle,pack('L', TimeUtils::iso2stamp($value)));
+						break;
+					case 2: //string
+						fwrite($handle,pack('L', strlen($value)));
+						for ($j = 0; $j < strlen($value); ++$j) {
+							fwrite($handle,pack('C', ord($value[$j])));
+						}
+						break;
+					case 3: //int
+						fwrite($handle,pack('L', intval($value)));
+					  break;
+					default: // not defined => string
+					fwrite($handle,pack('L', strlen($value)));
+					for ($j = 0; $j < strlen($value); ++$j) {
+						fwrite($handle,pack('C', ord($value[$j])));
+					}
+				}
 			}
 		}
 	}
 
-	public function loadBin($handle, $paramsNumber, $paramsSizes, $paramsTypes)
+	public function loadBin($handle)
 	{
-		$array = unpack('L6int',fread($handle,6*4));
-		$this->id         = $array['int1'];
-		$this->index      = $array['int2'];
-		$this->start      = $array['int3'];
-		$this->stop       = $array['int4'];
-		$this->isNew      = $array['int5'];
-		$this->isModified = $array['int6'];
-
-		for ($i = 0; $i < $paramsNumber; $i++) {
-		  $this->params[$i] = null;
-
-		  for ($j = 0; $j < $paramsSizes[$i]; $j++)
-		  {
-				$val = unpack('dval',fread($handle,8));
+		parent::loadBin($handle);
 
-				if ($paramsTypes[$i] == '2') // string
-				{
-					$this->params[$i] = fread($handle,$val['val']);
-				}
-				else
-				{
-					if ($paramsTypes[$i] == '1')
-						$this->params[$i] .= TimeUtils::stamp2iso($val['val']);
-					else
-						$this->params[$i] .= $val['val'];
-
-					if ($j != $paramsSizes[$i] - 1) $this->params[$i] .= ',';
+		foreach ($this->cacheObject->getParametersInfo() as $parameter) {
+		  $size = $parameter['size'];
+			$id = $parameter['id'];
+
+
+			$values = array();
+		  for ($i = 0; $i < $size; $i++)
+		  {
+				$val = "";
+				switch ($parameter['type']) {
+					case 0: //double
+						if (!$res = unpack('dval',fread($handle,8))) {
+							break;
+						}
+						$val = $res['val'];
+					  break;
+					case 1: //date (timestamp)
+						if (!$res = unpack('Lval',fread($handle,4))) {
+							break;
+						}
+						$val = $res['val'];
+						break;
+					case 2: //string
+						if (!$res = unpack('Llength',fread($handle,4))) {
+							break;
+						}
+						$length = $res['length'];
+						$val = "";
+						for ($j = 0; $j < $length; ++$j) {
+							if (!$res = unpack('Cval',fread($handle,1))) {
+								break;
+							}
+							$val .= chr($res['val']);
+						}
+
+						break;
+					case 3: //int
+						if (!$res = unpack('Lval',fread($handle,4))) {
+							break;
+						}
+						$val = $res['val'];
+					  break;
+					default: // not defined => string
+						if (!$res = unpack('Llength',fread($handle,4))) {
+							break;
+						}
+						$length = $res['length'];
+						$val = "";
+						for ($j = 0; $j < $length; ++$j) {
+							if (!$res = unpack('Cval',fread($handle,1))) {
+								break;
+							}
+							$val .= chr($res['val']);
+						}
 				}
+
+				$values[] = $val;
 			}
-		}
 
+			$this->params[$id] = implode(',',$values);
+		}
 	}
 
 	public function dump()
@@ -101,7 +141,7 @@ class CatalogCacheIntervalObject extends TimeTableCacheIntervalObject
 		parent::dump();
 		echo "               parameters = ";
 		foreach ($this->params as $param) {
-			echo $param.", ";
+			echo $param." - ";
 		}
 		echo PHP_EOL;
 	}
diff --git a/php/classes/CatalogCacheMgr.php b/php/classes/CatalogCacheMgr.php
index 26f91d2..ff2cacd 100644
--- a/php/classes/CatalogCacheMgr.php
+++ b/php/classes/CatalogCacheMgr.php
@@ -6,6 +6,7 @@
 
 class CatalogCacheMgr extends TimeTableCacheMgr
 {
+	const DEFAULT_PARAM_ID_PREFIX = 'cat_param_id_';
 
 	function __construct() {
 		$this->objectMgr  = new CatalogMgr();
@@ -15,55 +16,38 @@ class CatalogCacheMgr extends TimeTableCacheMgr
 	  return "cacheCat";
 	}
 
-	protected function resetCache() {
+	protected function resetCache($options = array()) {
     $this->cache = new CatalogCacheObject();
-  }
-
-	public function initObjectCache($options = array()) {
-		$result = parent::initObjectCache($options);
-		if (!$result['success']) {
-			return $result;
+		if (!empty($options['nparams'])) {
+			for ($i = 0; $i < (int)$options['nparams']; $i++) {
+				$this->cache->addParameter(CatalogCacheMgr::DEFAULT_PARAM_ID_PREFIX.(string)($i+1), 'column_'.(string)($i+1), 1, 0);
+			}
 		}
-
-		//init parameters
-		$nparams = isset($options['nparams']) ? $options['nparams'] : 1;
-		$this->cache->setParamsNumber((int)$nparams);
-
-		$paramHeaders = array();
-
-		for ($i = 0; $i < (int)$nparams; $i++) {
-			$paramHeaders[$i]['id'] = 'id_'.(string)($i+1);
-			$paramHeaders[$i]['name'] = 'column_'.(string)($i+1);
-			$paramHeaders[$i]['size'] = 1;
-			$paramHeaders[$i]['type'] = 'Float';
-
-		}
-		$this->cache->setParamsSizes($paramHeaders);
-		$this->cache->setParamsTypes($paramHeaders);
-		//Save cache file
-		return $result + array('parameters' => $paramHeaders);
-	}
-
-	public function initFromObject($id, $type)
-	{
-		$result = parent::initFromObject($id, $type);
-		if (!$result['success']) {
-			return $result;
+		else if (!empty($options['parameters'])) {
+			$index = 0;
+			foreach ($options['parameters'] as $parameter) {
+				if (array_key_exists('id',$parameter) && !empty($parameter['id'])) {
+					$id = $parameter['id'];
+				}
+				else if (array_key_exists('ID',$parameter) && !empty($parameter['ID'])) {
+					$id = $parameter['ID'];
+				}
+				else {
+					$id = 'cat_param_id_'.$index;
+				}
+				$this->cache->addParameter($id, $parameter['name'], intval($parameter['size']), intval($parameter['type']));
+				++$index;
+			}
 		}
+		return array('parameters' => $this->cache->getParametersInfo());
+  }
 
-		$params_desc = $this->objectMgr->getCatalogParamDescription($id, $name, FALSE, $type);
+	protected function loadAdditionalDescription($id, $type) {
+		$params_desc = $this->objectMgr->getCatalogParamDescription($id, "", FALSE, $type);
 		if (!$params_desc['success']) {
-			return $params_desc;
+			return array();
 		}
-
-		$paramHeaders = $params_desc['parameters'];
-
-		$this->cache->setParamsNumber(count($paramHeaders));
-		$this->cache->setParamsSizes($paramHeaders);
-		$this->cache->setParamsTypes($paramHeaders);
-
-		//Save cache file
-		return $result+ array('parameters' => $paramHeaders);
+		return array('parameters' => $params_desc['parameters']);
 	}
 
 	public function initFromTmpObject($folderId, $name) {
@@ -77,34 +61,45 @@ class CatalogCacheMgr extends TimeTableCacheMgr
 			return $params_desc;
 		}
 
-		$paramHeaders = $params_desc['parameters'];
-
-		$this->cache->setParamsNumber(count($paramHeaders));
-		$this->cache->setParamsSizes($paramHeaders);
-		$this->cache->setParamsTypes($paramHeaders);
+		foreach ($params_desc['parameters'] as $parameter) {
+			$this->cache->addParameter($parameter['id'], $parameter['name'], intval($parameter['size']), intval($parameter['type']));
+		}
 
-		return $result+ array('parameters' => $paramHeaders);
+		return $result+ array('parameters' => $this->cache->getParametersInfo());
 	}
 
 	public function initFromUploadedFile($name, $format)
 	{
+
+
+
+
 		$result = parent::initFromUploadedFile($name, $format);
 		if (!$result['success']) {
 			return $result;
 		}
 
-		$params_desc = $this->objectMgr->getCatalogParamDescription($id, $name, FALSE, $type);
+		$info = $this->objectMgr->getUploadedObject($name, $format,TRUE);
+		foreach ($info['parameters'] as $parameter) {
+			$this->cache->addParameter($parameter['id'], $parameter['name'], intval($parameter['size']), intval($parameter['type']));
+		}
+
+
+
+		/*$params_desc = $this->objectMgr->getCatalogParamDescription($id, $name, FALSE, $type);
 		if (!$params_desc['success']) {
 			return $params_desc;
 		}
 
-		$paramHeaders = $params_desc['parameters'];
+		foreach ($params_desc['parameters'] as $parameter) {
+			$this->cache->addParameter($parameter['id'], $parameter['name'], intval($parameter['size']), intval($parameter['type']));
+		}
+
+		$paramHeaders = $params_desc['parameters'];*/
 
-		$this->cache->setParamsNumber(count($paramHeaders));
-		$this->cache->setParamsSizes($paramHeaders);
-		$this->cache->setParamsTypes($paramHeaders);
+		//$this->cache->setParameters($paramHeaders);
 
-		return $result+ array('parameters' => $paramHeaders);
+	return $result+ array('parameters' => $info['parameters']);
 	}
 
 }
diff --git a/php/classes/CatalogCacheObject.php b/php/classes/CatalogCacheObject.php
index 4de4828..d5f0268 100644
--- a/php/classes/CatalogCacheObject.php
+++ b/php/classes/CatalogCacheObject.php
@@ -2,169 +2,115 @@
 
 class CatalogCacheObject extends TimeTableCacheObject
 {
-	private $paramsNumber;
-	private $paramsSizes = array();
-	private $paramsTypes = array();
-
-	public function addInterval($interval, $isNew = false, $index = -1)
-	{
-		$intervalObj = new CatalogCacheIntervalObject($this->lastId, count($this->intervals));
-		++$this->lastId;
-		$intervalObj->setStartFromISO($interval['start']);
-		$intervalObj->setStopFromISO($interval['stop']);
-		// for catalog
-		$intervalObj->setParams($interval['paramTable']);
-
-		$intervalObj->setIsNew($isNew);
-		array_push($this->intervals, $intervalObj);
-
-		if ($index < 0)
-			array_push($this->indexes, count($this->intervals) - 1);
-		else
-			array_splice($this->indexes, $index, 0, array(count($this->intervals) - 1));
-
-		if ($isNew)
-			$this->isModified = true;
+	private $parameters = array();
+
+	public function reset() {
+		parent::reset();
+		$this->parameters = array();
+		//ToDo - Init sort and filters for Catalog
+		/*unset($this->filter);
+		$this->filter = new TimeTableCacheFilterObject();;
+		unset($this->sort);
+		$this->sort = new TimeTableCacheSortObject();*/
+	}
 
-		return $intervalObj;
+	protected function createNewIntervalObject($id, $index = -1) {
+		return new CatalogCacheIntervalObject($this, $id, $index);
 	}
 
-	public function setParamsNumber($number)
+	public function addInterval($interval, $isNew = false, $index = -1)
 	{
-	    $this->paramsNumber = $number;
+		$intervalObj = parent::addInterval($interval, $isNew, $index);
+		for ($i = 0; $i < count($interval['paramTable']); ++$i) {
+			$intervalObj->setParamValue($this->parameters[$i]['id'], $interval['paramTable'][$i]);
+		}
+		return $intervalObj;
 	}
 
-	public function setParamsSizes($params)
+	public function addParameter($id, $name, $size, $type)
 	{
-		for ($i = 0; $i < $this->paramsNumber; $i++)
-			$this->paramsSizes[$i] = $params[$i]['size'];
+	    $this->parameters[] = array(
+				'id' => $id,
+				'name' => $name,
+				'size' => $size,
+				'type' => $type,
+			);
 	}
 
-	public function setParamsTypes($params)
-	{
-		for ($i = 0; $i < $this->paramsNumber; $i++)
-			$this->paramsTypes[$i] = $params[$i]['type'];
+	public function getParametersInfo() {
+		return $this->parameters;
 	}
 
-	public function writeBin($handle)
+	public function writeAdditionalHeaderBin($handle)
 	{
-		//Magic key ("TTC")
-		fwrite($handle,pack('C3',ord('T'),ord('T'),ord('C')));
-
-		//Version
-		fwrite($handle,pack('L',TimeTableCacheObject::$format_version));
-
-		//Token
-		for ($i = 0; $i < TimeTableCacheObject::$token_len; ++$i)
-			fwrite($handle,pack('C',ord($this->token[$i])));
-
-		//Modified
-		fwrite($handle,pack('L',$this->isModified));
-
-		//Filter
-		$this->filter->writeBin($handle);
-
-		//Sort
-		$this->sort->writeBin($handle);
-
-		//Params Number
-		fwrite($handle,pack('L',$this->paramsNumber));
-
-		//Params Sizes
-		for ($i = 0; $i < $this->paramsNumber; $i++)
-			fwrite($handle,pack('L',$this->paramsSizes[$i]));
-
-		//Params Types
-		for ($i = 0; $i < $this->paramsNumber; $i++)
-			fwrite($handle,pack('L',$this->paramsTypes[$i]));
-
-		//Intervals
-		fwrite($handle,pack('L2', count($this->intervals), $this->lastId));
-
-
-		foreach($this->intervals as $interval)
-			$interval->writeBin($handle,$this->paramsNumber,$this->paramsSizes, $this->paramsTypes);
-
-		//Indexes
-		fwrite($handle,pack('L',count($this->indexes)));
-		foreach($this->indexes as $index)
-			fwrite($handle,pack('L',$index));
+			//Params Number
+		fwrite($handle,pack('L',count($this->parameters)));
+		foreach ($this->parameters as $parameter) {
+				//Param Id length
+			fwrite($handle,pack('L',strlen($parameter['id'])));
+		  	//Param name length
+			fwrite($handle,pack('L',strlen($parameter['name'])));
+			  //Param Size
+			fwrite($handle,pack('L',$parameter['size']));
+				//Param Type
+			fwrite($handle,pack('L',$parameter['type']));
+				//Param Id
+			for ($i = 0; $i < strlen($parameter['id']); ++$i)
+					fwrite($handle,pack('C',ord($parameter['id'][$i])));
+				//Param name:
+			for ($i = 0; $i < strlen($parameter['name']); ++$i)
+					fwrite($handle,pack('C',ord($parameter['name'][$i])));
+		}
 	}
 
-    public function loadBin($handle) {
-		//Magic key ("TTC")
-		if (!$res = unpack('C3key',fread($handle,3)))
-			return false;
-
-		if (($res['key1'] != ord('T')) || ($res['key2'] != ord('T')) || ($res['key3'] != ord('C')))
-			return false;
-
-		//Version
-		if (!$res = unpack('Lversion',fread($handle,4)))
-			return false;
-		if (($res['version'] != TimeTableCacheObject::$format_version))
-			return false;
-
-		//Token
-		$token = "";
-		for ($i = 0; $i < TimeTableCacheObject::$token_len; ++$i)
-		{
-			if (!$res = unpack('Ctoken',fread($handle,1)))
+	protected function loadAdditionalHeaderBin($handle) {
+				//Params Number
+			if (!$res = unpack('Lnumber',fread($handle,4)))
 				return false;
-			$token .= chr($res['token']);
-		}
-		$this->token = $token;
-
-		//Modified
-		if (!$res = unpack('Lmodified',fread($handle,4)))
-			return false;
-		$this->isModified = $res['modified'];
+			$nbParams = $res['number'];
 
-		//Filter
-		$this->filter->loadBin($handle);
+			for ($i = 0; $i < $nbParams; ++$i) {
+					//Param Id length
+		 		if (!$res = unpack('Lidlength',fread($handle,4)))
+					return false;
+				$idlength = $res['idlength'];
 
-		//Sort
-		$this->sort->loadBin($handle);
-
-		//ParamsNumber
-		if (!$res = unpack('Lnumber',fread($handle,4)))
-			return false;
-		$this->paramsNumber = $res['number'];
-
-		//ParamsSizes
-		for ($i = 0; $i < $this->paramsNumber; $i++) {
-		  if (!$res = unpack('Lsize',fread($handle,4)))
-			  return false;
-		  $this->paramsSizes[$i] = $res['size'];
-		}
-		//ParamsTypes
-		for ($i = 0; $i < $this->paramsNumber; $i++) {
-		  if (!$res = unpack('Ltype',fread($handle,4)))
-			  return false;
-		  $this->paramsTypes[$i] = $res['type'];
-		}
-		//Intervals
-		$res = unpack('L2data',fread($handle,2*4));
-		$nbIntervals  = $res['data1'];
-		$this->lastId = $res['data2'];
+					//Param Name length
+			  if (!$res = unpack('Lnamelength',fread($handle,4)))
+					return false;
+				$namelength = $res['namelength'];
 
-		for ($i = 0; $i < $nbIntervals; ++$i)
-		{
-			$interval = new CatalogCacheIntervalObject(-1);
-			$interval->loadBin($handle, $this->paramsNumber, $this->paramsSizes, $this->paramsTypes);
-			array_push($this->intervals, $interval);
-		}
+					//Param Size
+			 if (!$res = unpack('Lsize',fread($handle,4)))
+				return false;
+			 $size = $res['size'];
+
+				 //Param Type
+				if (!$res = unpack('Ltype',fread($handle,4)))
+					return false;
+				$type = $res['type'];
+
+				//Param Id
+				$id = "";
+				for ($j = 0; $j < $idlength; ++$j)
+				{
+						if (!$res = unpack('Cid',fread($handle,1)))
+							return false;
+						$id .= chr($res['id']);
+					}
 
-		//Indexes
-		$res = unpack('Ldata',fread($handle,4));
-		$nbIndexes  = $res['data'];
-		for ($i = 0; $i < $nbIndexes; ++$i)
-		{
-			$res = unpack('Lindex',fread($handle,4));
-			array_push($this->indexes, $res['index']);
-		}
+					//Param Name
+				$name = "";
+				for ($j = 0; $j < $namelength; ++$j)
+				{
+					if (!$res = unpack('Cname',fread($handle,1)))
+						return false;
+					$name .= chr($res['name']);
+				}
 
-		return true;
+				$this->addParameter($id, $name, $size, $type);
+			}
+			return true;
 	}
 
 	public function modifyIntervalFromId($cacheId, $data) {
@@ -178,7 +124,7 @@ class CatalogCacheObject extends TimeTableCacheObject
 					if (strpos($key, 'param') !== FALSE) {
 						$params = $interval->getParams();
 						$paramIndex = (int)substr($key,5);
-						$params[$paramIndex-2] = $val;
+						$params[$paramIndex-2] = $value;
 						$interval->setParams($params);
 						$interval->setIsModified(true);
 						$this->isModified = true;
@@ -190,6 +136,34 @@ class CatalogCacheObject extends TimeTableCacheObject
 
 		return false;
 	}
+
+	public function dump() {
+		echo " => CatalogCacheObject : token = ".$this->token.", nb intervals = ".count($this->intervals).", last id = ".$this->lastId.", nb indexes = ".count($this->indexes).PHP_EOL;
+		echo PHP_EOL;
+
+		echo " => Parameters : ".PHP_EOL;
+		foreach ($this->parameters as $parameter) {
+			echo "    * id = ".$parameter['id'].", name = ".$parameter['name'].", size = ".$parameter['size'].", type = ".$parameter['type'].PHP_EOL;
+		}
+		echo PHP_EOL;
+
+		$this->filter->dump();
+		echo PHP_EOL;
+
+		$this->sort->dump();
+		echo PHP_EOL;
+
+		foreach ($this->intervals as $interval)
+			$interval->dump();
+		echo PHP_EOL;
+
+		echo " => Indexes list : ";
+		foreach ($this->indexes as $index)
+		{
+			echo $index.", ";
+		}
+		echo PHP_EOL;
+	}
 }
 
  ?>
diff --git a/php/classes/CatalogMgr.php b/php/classes/CatalogMgr.php
index 1a6aa0c..e35bac9 100644
--- a/php/classes/CatalogMgr.php
+++ b/php/classes/CatalogMgr.php
@@ -21,18 +21,6 @@ class CatalogMgr extends TimeTableMgr
 		}
 	}
 
-	public function getUploadedObject($name, $format, $onlyDescription = false)
-	{
-		if ($format == 'VOT')
-		{
-			$attributesToReturn = $this->vot2amda(USERTEMPDIR.$name, $onlyDescription);
-		}
-		$attributesToReturn['objName'] = $name;
-		$attributesToReturn['objFormat'] = $format;
-
-		return  $attributesToReturn;
-	}
-
 	public function getTmpObject($folderId, $name, $onlyDescription = false)
 	{
 		$filePath = USERWORKINGDIR.$folderId.'/'.$name.'.xml';
@@ -396,6 +384,36 @@ class CatalogMgr extends TimeTableMgr
 
       }
 
+			public function getUploadedObject($name, $format, $onlyDescription = false)
+			{
+				$result = TimeTableMgr::getUploadedObject($name, $format, $onlyDescription);
+				if (!isset($result['success']) || !$result['success']) {
+
+					return array('success' => FALSE, 'error' => 'Error to retrieve catalog info');
+				}
+
+				$this->objectDom->load(USERTEMPDIR . $name . '.xml');
+
+				$xpath = new DOMXPath($this->objectDom);
+
+					// params header
+				$paramsNodes =  $xpath->query('//parameters/parameter');
+				$paramsArray = array();
+
+				if ($paramsNodes->length > 0)
+				{
+					foreach ($paramsNodes as $paramNode)
+					{
+						$oneParam = array();
+						foreach ($paramNode->attributes as $attr)
+							$oneParam[$attr->nodeName] = $attr->nodeValue;
+							$paramsArray[] = $oneParam;
+						}
+					}
+
+					return $result + array('parameters' => $paramsArray);
+			}
+
 // 	public function modifyObject($p) {
 // 		$folder = $this->getObjectFolder($p->id);
 //
@@ -428,98 +446,6 @@ class CatalogMgr extends TimeTableMgr
 // 		}
 // 	}
 
-/*
-* Uploaded vot catalog => convert to AMDA tmp
-*/
-	protected function vot2amda($tmp_file, $onlyDescription = false)
-	{
-		// Load Catalog
-		$this->objectDom->load($tmp_file);
-		$objToGet = $this->objectDom->getElementsByTagName('TABLEDATA')->item(0);
-
-		$attributes = $objToGet->childNodes;
-		$paramsNodes = $this->objectDom->getElementsByTagName('FIELD');
-		$paramsNumber = $paramsNodes->length;
-
-		foreach($attributes as $attribute)
-		{
-			if ($attribute->tagName == 'TR')
-			{
-				$start = $attribute->getElementsByTagName('TD')->item(0)->nodeValue;
-				$stop = $attribute->getElementsByTagName('TD')->item(1)->nodeValue;
-				$params = array();
-
-				for ($i = 2; $i < $paramsNumber; $i++)
-				{
-					$param = $attribute->getElementsByTagName('TD')->item($i)->nodeValue;
-
-					if ($paramsNodes->item($i)->hasAttribute('arraysize'))
-					{
-						$param = join(",",explode(" ",trim($param)));
-					}
-					$params[] = $param;
-				}
-				if (!$onlyDescription)
-					$attributesToReturn['intervals'][] = array('start' => $start, 'stop' => $stop, 'paramTable' => $params);
-			}
-		}
-
-		if ($paramsNumber > 2)
-		{
-			$paramsArray = array();
-			for ($i = 2; $i < $paramsNumber; $i++)
-			{
-				$oneParam = array();
-				$paramNode = $paramsNodes->item($i);
-
-				if ($paramNode->hasAttribute('arraysize'))
-				{
-					$oneParam['size'] = $paramNode->getAttribute('arraysize');
-				}
-				else
-				{
-					$oneParam['size'] = 1;
-				}
-
-				foreach ($paramNode->attributes as $attr)
-				{
-					if ($attr->nodeName == 'datatype')
-					{
-						$datatype = $attr->nodeValue;
 
-						if ($paramNode->hasAttribute('xtype') && (($paramNode->getAttribute('xtype') == 'dateTime') || ($paramNode->getAttribute('xtype') == 'iso8601')))
-						{
-							$oneParam['type'] = 1;
-							$paramNode->setAttribute('xtype','dateTime');
-							$paramNode->setAttribute('size',1);
-						}
-						else if ($datatype == 'char')
-						{
-							$oneParam['type'] = 2;// string
-							$paramNode->setAttribute('size', 1);
-						}
-						else
-						{
-							$oneParam['type'] = 0;//'Double';
-						}
-					}
-					else if ($attr->nodeName != 'arraysize')
-					{
-						$oneParam[$attr->nodeName] = $attr->nodeValue;
-					}
-				}
-				$paramsArray[] = $oneParam;
-			}
-			$attributesToReturn['success'] = true;
-			$attributesToReturn['parameters'] = $paramsArray;
-		}
-
-		$suffix = explode('.', basename($tmp_file));
-		$attributesToReturn['name'] = basename($tmp_file, '.'.$suffix[1]);
-		$attributesToReturn['created'] = date('Y-m-d')."T".date('H:i:s');
-		$attributesToReturn['description'] = htmlspecialchars($this->objectDom->getElementsByTagName('DESCRIPTION')->item(0)->nodeValue);
-
-		return($attributesToReturn);
-	}
 }
 ?>
diff --git a/php/classes/TimeTableCacheIntervalObject.php b/php/classes/TimeTableCacheIntervalObject.php
index decd600..8865e23 100644
--- a/php/classes/TimeTableCacheIntervalObject.php
+++ b/php/classes/TimeTableCacheIntervalObject.php
@@ -1,6 +1,7 @@
 <?php
 class TimeTableCacheIntervalObject
 {
+	protected $cacheObject = NULL;
 	protected $id         = -1;
 	protected $index      = -1;
 	protected $start      = 0;
@@ -8,7 +9,8 @@ class TimeTableCacheIntervalObject
 	protected $isNew      = false;
 	protected $isModified = false;
 
-	function __construct($id, $index = -1) {
+	function __construct($cacheObject, $id, $index = -1) {
+		$this->cacheObject = $cacheObject;
 		$this->id = $id;
 		$this->index = $index;
 	}
diff --git a/php/classes/TimeTableCacheMgr.php b/php/classes/TimeTableCacheMgr.php
index 3ed0036..4c78c5c 100644
--- a/php/classes/TimeTableCacheMgr.php
+++ b/php/classes/TimeTableCacheMgr.php
@@ -21,21 +21,27 @@
     return USERTTDIR;
   }
 
-  protected function resetCache() {
+  protected function resetCache($options = array()) {
     $this->cache = new TimeTableCacheObject();
+    return array();
+  }
+
+  protected function loadAdditionalDescription($id, $type) {
+    return array();
   }
 
 	public function initObjectCache($options = array()) {
 		//Create new cache
-		$this->resetCache();
+		$info = $this->resetCache($options);
 
 		//Save cache file
-		return array('success' => $this->saveToFile(), 'token' => $this->cache->getToken(), 'status' => $this->cache->getStatus());
+		return array('success' => $this->saveToFile(), 'token' => $this->cache->getToken(), 'status' => $this->cache->getStatus()) + $info;
 	}
 
 	public function initFromObject($id, $type) {
+    $options = $this->loadAdditionalDescription($id, $type);
 		//Create new cache
-		$this->resetCache();
+		$info = $this->resetCache($options);
 
 		//Load intervals from object file and add to cache
 		$intervals_res = $this->objectMgr->loadIntervalsFromObject($id,$type);
@@ -55,7 +61,7 @@
 		$this->cache->updateIndexes();
 
 		//Save cache file
-		return array('success' => $this->saveToFile(), 'token' => $this->cache->getToken(), 'status' => $this->cache->getStatus());
+		return array('success' => $this->saveToFile(), 'token' => $this->cache->getToken(), 'status' => $this->cache->getStatus()) + $info;
 	}
 
        public function initFromCatalog($id, $type) {
diff --git a/php/classes/TimeTableCacheObject.php b/php/classes/TimeTableCacheObject.php
index cb299ce..7bd81f2 100644
--- a/php/classes/TimeTableCacheObject.php
+++ b/php/classes/TimeTableCacheObject.php
@@ -20,8 +20,7 @@ class TimeTableCacheObject
 
 	function __construct() {
 		$this->token  = $this->getRandomToken();
-		$this->filter = new TimeTableCacheFilterObject();
-		$this->sort   = new TimeTableCacheSortObject();
+		$this->reset();
 	}
 
 	public function reset() {
@@ -39,8 +38,12 @@ class TimeTableCacheObject
 		$this->isModified = $isModified;
 	}
 
+	protected function createNewIntervalObject($id, $index = -1) {
+		return new TimeTableCacheIntervalObject($this, $id, $index);
+	}
+
 	public function addInterval($interval, $isNew = false, $index = -1) {
-		$intervalObj = new TimeTableCacheIntervalObject($this->lastId, count($this->intervals));
+		$intervalObj = $this->createNewIntervalObject($this->lastId, count($this->intervals));
 		++$this->lastId;
 		$intervalObj->setStartFromISO($interval['start']);
 		$intervalObj->setStopFromISO($interval['stop']);
@@ -93,12 +96,12 @@ class TimeTableCacheObject
 				foreach ($data as $key => $value) {
 					switch ($key) {
 						case 'start' :
-							$interval->setStartFromISO($start);
+							$interval->setStartFromISO($value);
 							$interval->setIsModified(true);
 							$this->isModified = true;
 							break;
 						case 'stop':
-							$interval->setStopFromISO($stop);
+							$interval->setStopFromISO($value);
 							$interval->setIsModified(true);
 							$this->isModified = true;
 							break;
@@ -174,7 +177,7 @@ class TimeTableCacheObject
 		$this->reset();
 
 		foreach ($merged_intervals as $merged_interval) {
-			$interval = new TimeTableCacheIntervalObject($this->lastId, count($this->intervals));
+			$interval = $this->createNewIntervalObject($this->lastId, count($this->intervals));
 			++$this->lastId;
 			$interval->setStartFromStamp($merged_interval["start"]);
 			$interval->setStopFromStamp($merged_interval["stop"]);
@@ -417,10 +420,14 @@ class TimeTableCacheObject
 		//Sort
 		$this->sort->writeBin($handle);
 
+		//Additional info
+		$this->writeAdditionalHeaderBin($handle);
+
 		//Intervals
 		fwrite($handle,pack('L2',count($this->intervals), $this->lastId));
-		foreach($this->intervals as $interval)
+		foreach($this->intervals as $interval) {
 			$interval->writeBin($handle);
+		}
 
 		//Indexes
 		fwrite($handle,pack('L',count($this->indexes)));
@@ -463,13 +470,16 @@ class TimeTableCacheObject
 		//Sort
 		$this->sort->loadBin($handle);
 
+		//Additional info
+		$this->loadAdditionalHeaderBin($handle);
+
 		//Intervals
 		$res = unpack('L2data',fread($handle,2*4));
 		$nbIntervals  = $res['data1'];
 		$this->lastId = $res['data2'];
 		for ($i = 0; $i < $nbIntervals; ++$i)
 		{
-			$interval = new TimeTableCacheIntervalObject(-1);
+			$interval = $this->createNewIntervalObject(-1);
 			$interval->loadBin($handle);
 			array_push($this->intervals, $interval);
 		}
@@ -486,6 +496,14 @@ class TimeTableCacheObject
 		return true;
 	}
 
+	protected function loadAdditionalHeaderBin($handle) {
+		// Nothing to do for a TT
+	}
+
+	protected function writeAdditionalHeaderBin($handle) {
+		// Nothing to do for a TT
+	}
+
 	protected function getRandomToken() {
 		$letters = 'abcefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
 		return substr(str_shuffle($letters), 0, TimeTableCacheObject::$token_len);
diff --git a/php/classes/TimeTableMgr.php b/php/classes/TimeTableMgr.php
index cc3be69..be88dee 100644
--- a/php/classes/TimeTableMgr.php
+++ b/php/classes/TimeTableMgr.php
@@ -242,22 +242,6 @@ class TimeTableMgr extends AmdaObjectMgr
 	 */
 	public function getUploadedObject($name, $format, $onlyDescription = false)
 	{
-		if (strpos($name, '.txt') !== false || strpos($name, '.asc') !== false || strpos($name, '.') == false) {
-			$attributesToReturn = $this->textToAmda(USERTEMPDIR . $name, $onlyDescription);
-			$attributesToReturn['objName'] = $name;
-			$attributesToReturn['objFormat'] = $format;
-
-			return $attributesToReturn;
-		}
-
-		if ($format == 'VOT') {
-			$attributesToReturn = $this->vot2amda(USERTEMPDIR . $name, $onlyDescription);
-			$attributesToReturn['objName'] = $name;
-			$attributesToReturn['objFormat'] = $format;
-
-			return $attributesToReturn;
-		}
-
 		if (strpos($name, '.xml') !== false) {
 			$temp = explode('.xml', $name);
 			$name = $temp[0];
@@ -299,10 +283,12 @@ class TimeTableMgr extends AmdaObjectMgr
 							case 'created':
 								$attributesToReturn['created'] = $attribute->nodeValue;
 								break;
-							case 'chain':
-							case 'source':
+							case 'description':
 								$attributesToReturn['description'] = $attribute->nodeValue;
 								break;
+							case 'history':
+									$attributesToReturn['history'] = $attribute->nodeValue;
+									break;
 							default:
 								break;
 						}
@@ -310,107 +296,10 @@ class TimeTableMgr extends AmdaObjectMgr
 				}
 			}
 		}
+		$attributesToReturn['success'] = TRUE;
 		return $attributesToReturn;
 	}
 
-	/*
-	* Uploaded text file => convert to array
-	*/
-
-	/**
-	 * Convert text to AMDA attributes
-	 * @param $tmp_file
-	 * @param bool $onlyDescription
-	 * @return mixed
-	 */
-	protected function textToAmda($tmp_file, $onlyDescription = false)
-	{
-		$suffix = explode('.', basename($tmp_file));
-		$lines = file($tmp_file, FILE_SKIP_EMPTY_LINES);
-		$description = "Uploaded Time Table" . PHP_EOL;
-
-		$recordsNumber = count($lines);
-		$descNumber = 0;
-
-		foreach ($lines as $line) {
-			$line = trim($line);
-			if ($line[0] == '#') { // Comment
-				$description = $description . PHP_EOL . substr($line, 1, -1);
-			} else {
-				$line = preg_replace('/[-:\/T\s]+/', ' ', $line);
-				$isoFormat = 'Y-m-dTH:i:s';
-				$doyFormat = 'Y z H i s';
-				$doyRegex = '(\d{4}) (\d{3}) (\d{2}) (\d{2}) (\d{2})( \d{2})?';
-
-				if (preg_match('/^' . $doyRegex . ' ' . $doyRegex . '$/', $line)) {
-					$start = DateTime::createFromFormat($doyFormat, substr($line, 0, 17));
-					$stop = DateTime::createFromFormat($doyFormat, substr($line, 18));
-					$startDate = $start->sub(new DateInterval('P1D'))->format($isoFormat);
-					$stopDate = $stop->sub(new DateInterval('P1D'))->format($isoFormat);
-				} else {
-					$dateLength = round((strlen($line)-1) / 2);
-
-					$start = explode(' ', substr($line, 0, $dateLength) . ' 00');
-					$startTime = strtotime("$start[0]/$start[1]/$start[2] $start[3]:$start[4]:$start[5]");
-
-					$stop = explode(' ', substr($line, $dateLength + 1) . ' 00');
-					$stopTime = strtotime("$stop[0]/$stop[1]/$stop[2] $stop[3]:$stop[4]:$stop[5]");
-					if (is_numeric($startTime) && is_numeric($stopTime)) {
-						$startDate = date($isoFormat, $startTime);
-						$stopDate = date($isoFormat, $stopTime);
-					} else {
-						$description = $description . PHP_EOL . $line;
-						$descNumber++;
-						continue;
-					}
-				}
-
-				if (!$onlyDescription) {
-					$attributesToReturn['intervals'][] = ['start' => $startDate, 'stop' => $stopDate];
-				}
-			}
-		}
-		if ($recordsNumber == $descNumber) {
-			$description = 'Looks like we can not read your time format...' . PHP_EOL . $description;
-		}
-
-		$attributesToReturn['description'] = $description;
-		$attributesToReturn['name'] = basename($tmp_file, '.' . $suffix[1]);
-		$attributesToReturn['created'] = date('Y-m-d\TH:i:s');
-		return $attributesToReturn;
-	}
-
-	/**
-	 * Convert VOTable time table to AMDA attributes
-	 * @param $tmp_file
-	 * @param bool $onlyDescription
-	 * @return mixed
-	 */
-	protected function vot2amda($tmp_file, $onlyDescription = false)
-	{
-		// Load Time table
-		$this->objectDom->load($tmp_file);
-		$objToGet = $this->objectDom->getElementsByTagName('TABLEDATA')->item(0);
-		$attributesToReturn['name'] = $tmp_file;
-		$attributes = $objToGet->childNodes;
-
-		/** @var DOMElement $attribute */
-		foreach ($attributes as $attribute) {
-			if ($attribute->tagName == 'TR') {
-				$start = $attribute->getElementsByTagName('TD')->item(0)->nodeValue;
-				$stop = $attribute->getElementsByTagName('TD')->item(1)->nodeValue;
-				if (!$onlyDescription) {
-					$attributesToReturn['intervals'][] = ['start' => $start, 'stop' => $stop];
-				}
-			}
-		}
-		$suffix = explode('.', basename($tmp_file));
-		$attributesToReturn['name'] = basename($tmp_file, '.' . $suffix[1]);
-		$attributesToReturn['created'] = date('Y-m-d') . "T" . date('H:i:s');
-		$description = $this->objectDom->getElementsByTagName('DESCRIPTION')->item(0)->nodeValue;
-		$attributesToReturn['description'] = htmlspecialchars($description);
-		return ($attributesToReturn);
-	}
 
 	/*****************************************************************
 	 *                           PUBLIC FUNCTIONS
--
libgit2 0.21.2