]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/framework/Data/SqlMap/Configuration/TSqlMapXmlConfiguration.php
Add Baculum
[bacula/bacula] / gui / baculum / framework / Data / SqlMap / Configuration / TSqlMapXmlConfiguration.php
1 <?php
2 /**
3  * TSqlMapXmlConfigBuilder, TSqlMapXmlConfiguration, TSqlMapXmlMappingConfiguration classes file.
4  *
5  * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
6  * @link http://www.pradosoft.com/
7  * @copyright Copyright &copy; 2005-2013 PradoSoft
8  * @license http://www.pradosoft.com/license/
9  * @version $Id: TSqlMapXmlConfiguration.php 3245 2013-01-07 20:23:32Z ctrlaltca $
10  * @package System.Data.SqlMap.Configuration
11  */
12
13 Prado::using('System.Data.SqlMap.Configuration.TSqlMapStatement');
14
15 /**
16  * TSqlMapXmlConfig class file.
17  *
18  * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
19  * @version $Id: TSqlMapXmlConfiguration.php 3245 2013-01-07 20:23:32Z ctrlaltca $
20  * @package System.Data.SqlMap.Configuration
21  */
22 abstract class TSqlMapXmlConfigBuilder
23 {
24         /**
25          * Create an instance of an object give by the attribute named 'class' in the
26          * node and set the properties on the object given by attribute names and values.
27          * @param SimpleXmlNode property node
28          * @return Object new instance of class with class name given by 'class' attribute value.
29          */
30         protected function createObjectFromNode($node)
31         {
32                 if(isset($node['class']))
33                 {
34                         $obj = Prado::createComponent((string)$node['class']);
35                         $this->setObjectPropFromNode($obj,$node,array('class'));
36                         return $obj;
37                 }
38                 throw new TSqlMapConfigurationException(
39                         'sqlmap_node_class_undef', $node, $this->getConfigFile());
40         }
41
42         /**
43          * For each attributes (excluding attribute named in $except) set the
44          * property of the $obj given by the name of the attribute with the value
45          * of the attribute.
46          * @param Object object instance
47          * @param SimpleXmlNode property node
48          * @param array exception property name
49          */
50         protected function setObjectPropFromNode($obj,$node,$except=array())
51         {
52                 foreach($node->attributes() as $name=>$value)
53                 {
54                         if(!in_array($name,$except))
55                         {
56                                 if($obj->canSetProperty($name))
57                                         $obj->{$name} = (string)$value;
58                                 else
59                                         throw new TSqlMapConfigurationException(
60                                                 'sqlmap_invalid_property', $name, get_class($obj),
61                                                 $node, $this->getConfigFile());
62                         }
63                 }
64         }
65
66         /**
67          * Gets the filename relative to the basefile.
68          * @param string base filename
69          * @param string relative filename
70          * @return string absolute filename.
71          */
72         protected function getAbsoluteFilePath($basefile,$resource)
73         {
74                 $basedir = dirname($basefile);
75                 $file = realpath($basedir.DIRECTORY_SEPARATOR.$resource);
76                 if(!is_string($file) || !is_file($file))
77                         $file = realpath($resource);
78                 if(is_string($file) && is_file($file))
79                         return $file;
80                 else
81                         throw new TSqlMapConfigurationException(
82                                 'sqlmap_unable_to_find_resource', $resource);
83         }
84
85         /**
86          * Load document using simple xml.
87          * @param string filename.
88          * @return SimpleXmlElement xml document.
89          */
90         protected function loadXmlDocument($filename,TSqlMapXmlConfiguration $config)
91         {
92                 if( strpos($filename, '${') !== false)
93                         $filename = $config->replaceProperties($filename);
94
95                 if(!is_file($filename))
96                         throw new TSqlMapConfigurationException(
97                                 'sqlmap_unable_to_find_config', $filename);
98                 return simplexml_load_string($config->replaceProperties(file_get_contents($filename)));
99         }
100
101         /**
102          * Get element node by ID value (try for attribute name ID as case insensitive).
103          * @param SimpleXmlDocument $document
104          * @param string tag name.
105          * @param string id value.
106          * @return SimpleXmlElement node if found, null otherwise.
107          */
108         protected function getElementByIdValue($document, $tag, $value)
109         {
110                 //hack to allow upper case and lower case attribute names.
111                 foreach(array('id','ID','Id', 'iD') as $id)
112                 {
113                         $xpath = "//{$tag}[@{$id}='{$value}']";
114                         foreach($document->xpath($xpath) as $node)
115                                 return $node;
116                 }
117         }
118
119         /**
120          * @return string configuration file.
121          */
122         protected abstract function getConfigFile();
123 }
124
125 /**
126  * TSqlMapXmlConfig class.
127  *
128  * Configures the TSqlMapManager using xml configuration file.
129  *
130  * @author Wei Zhuo <weizho[at]gmail[dot]com>
131  * @version $Id: TSqlMapXmlConfiguration.php 3245 2013-01-07 20:23:32Z ctrlaltca $
132  * @package System.Data.SqlMap.Configuration
133  * @since 3.1
134  */
135 class TSqlMapXmlConfiguration extends TSqlMapXmlConfigBuilder
136 {
137         /**
138          * @var TSqlMapManager manager
139          */
140         private $_manager;
141         /**
142          * @var string configuration file.
143          */
144         private $_configFile;
145         /**
146          * @var array global properties.
147          */
148         private $_properties=array();
149
150         /**
151          * @param TSqlMapManager manager instance.
152          */
153         public function __construct($manager)
154         {
155                 $this->_manager=$manager;
156         }
157
158         public function getManager()
159         {
160                 return $this->_manager;
161         }
162
163         protected function getConfigFile()
164         {
165                 return $this->_configFile;
166         }
167
168         /**
169          * Configure the TSqlMapManager using the given xml file.
170          * @param string SqlMap configuration xml file.
171          */
172         public function configure($filename=null)
173         {
174                 $this->_configFile=$filename;
175                 $document = $this->loadXmlDocument($filename,$this);
176
177                 foreach($document->xpath('//property') as $property)
178                         $this->loadGlobalProperty($property);
179
180                 foreach($document->xpath('//typeHandler') as $handler)
181                         $this->loadTypeHandler($handler);
182
183                 foreach($document->xpath('//connection[last()]') as $conn)
184                         $this->loadDatabaseConnection($conn);
185
186                 //try to load configuration in the current config file.
187                 $mapping = new TSqlMapXmlMappingConfiguration($this);
188                 $mapping->configure($filename);
189
190                 foreach($document->xpath('//sqlMap') as $sqlmap)
191                         $this->loadSqlMappingFiles($sqlmap);
192
193                 $this->resolveResultMapping();
194                 $this->attachCacheModels();
195         }
196
197         /**
198          * Load global replacement property.
199          * @param SimpleXmlElement property node.
200          */
201         protected function loadGlobalProperty($node)
202         {
203                 $this->_properties[(string)$node['name']] = (string)$node['value'];
204         }
205
206         /**
207          * Load the type handler configurations.
208          * @param SimpleXmlElement type handler node
209          */
210         protected function loadTypeHandler($node)
211         {
212                 $handler = $this->createObjectFromNode($node);
213                 $this->_manager->getTypeHandlers()->registerTypeHandler($handler);
214         }
215
216         /**
217          * Load the database connection tag.
218          * @param SimpleXmlElement connection node.
219          */
220         protected function loadDatabaseConnection($node)
221         {
222                 $conn = $this->createObjectFromNode($node);
223                 $this->_manager->setDbConnection($conn);
224         }
225
226         /**
227          * Load SqlMap mapping configuration.
228          * @param unknown_type $node
229          */
230         protected function loadSqlMappingFiles($node)
231         {
232                 if(strlen($resource = (string)$node['resource']) > 0)
233                 {
234                         if( strpos($resource, '${') !== false)
235                                 $resource = $this->replaceProperties($resource);
236
237                         $mapping = new TSqlMapXmlMappingConfiguration($this);
238                         $filename = $this->getAbsoluteFilePath($this->_configFile, $resource);
239                         $mapping->configure($filename);
240                 }
241         }
242
243         /**
244          * Resolve nest result mappings.
245          */
246         protected function resolveResultMapping()
247         {
248                 $maps = $this->_manager->getResultMaps();
249                 foreach($maps as $entry)
250                 {
251                         foreach($entry->getColumns() as $item)
252                         {
253                                 $resultMap = $item->getResultMapping();
254                                 if(strlen($resultMap) > 0)
255                                 {
256                                         if($maps->contains($resultMap))
257                                                 $item->setNestedResultMap($maps[$resultMap]);
258                                         else
259                                                 throw new TSqlMapConfigurationException(
260                                                         'sqlmap_unable_to_find_result_mapping',
261                                                                 $resultMap, $this->_configFile, $entry->getID());
262                                 }
263                         }
264                         if($entry->getDiscriminator()!==null)
265                                 $entry->getDiscriminator()->initialize($this->_manager);
266                 }
267         }
268
269         /**
270          * Set the cache for each statement having a cache model property.
271          */
272         protected function attachCacheModels()
273         {
274                 foreach($this->_manager->getMappedStatements() as $mappedStatement)
275                 {
276                         if(strlen($model = $mappedStatement->getStatement()->getCacheModel()) > 0)
277                         {
278                                 $cache = $this->_manager->getCacheModel($model);
279                                 $mappedStatement->getStatement()->setCache($cache);
280                         }
281                 }
282         }
283
284         /**
285          * Replace the place holders ${name} in text with properties the
286          * corresponding global property value.
287          * @param string original string.
288          * @return string string with global property replacement.
289          */
290         public function replaceProperties($string)
291         {
292                 foreach($this->_properties as $find => $replace)
293                         $string = str_replace('${'.$find.'}', $replace, $string);
294                 return $string;
295         }
296 }
297
298 /**
299  * Loads the statements, result maps, parameters maps from xml configuration.
300  *
301  * description
302  *
303  * @author Wei Zhuo <weizho[at]gmail[dot]com>
304  * @version $Id: TSqlMapXmlConfiguration.php 3245 2013-01-07 20:23:32Z ctrlaltca $
305  * @package System.Data.SqlMap.Configuration
306  * @since 3.1
307  */
308 class TSqlMapXmlMappingConfiguration extends TSqlMapXmlConfigBuilder
309 {
310         private $_xmlConfig;
311         private $_configFile;
312         private $_manager;
313
314         private $_document;
315
316         private $_FlushOnExecuteStatements=array();
317
318         /**
319          * Regular expressions for escaping simple/inline parameter symbols
320          */
321         const SIMPLE_MARK='$';
322         const INLINE_SYMBOL='#';
323         const ESCAPED_SIMPLE_MARK_REGEXP='/\$\$/';
324         const ESCAPED_INLINE_SYMBOL_REGEXP='/\#\#/';
325         const SIMPLE_PLACEHOLDER='`!!`';
326         const INLINE_PLACEHOLDER='`!!!`';
327
328         /**
329          * @param TSqlMapXmlConfiguration parent xml configuration.
330          */
331         public function __construct(TSqlMapXmlConfiguration $xmlConfig)
332         {
333                 $this->_xmlConfig=$xmlConfig;
334                 $this->_manager=$xmlConfig->getManager();
335         }
336
337         protected function getConfigFile()
338         {
339                 return $this->_configFile;
340         }
341
342         /**
343          * Configure an XML mapping.
344          * @param string xml mapping filename.
345          */
346         public function configure($filename)
347         {
348                 $this->_configFile=$filename;
349                 $document = $this->loadXmlDocument($filename,$this->_xmlConfig);
350                 $this->_document=$document;
351
352                 static $bCacheDependencies;
353                 if($bCacheDependencies === null)
354                         $bCacheDependencies = Prado::getApplication()->getMode() !== TApplicationMode::Performance;
355
356                 if($bCacheDependencies)
357                         $this->_manager->getCacheDependencies()
358                                         ->getDependencies()
359                                         ->add(new TFileCacheDependency($filename));
360
361                 foreach($document->xpath('//resultMap') as $node)
362                         $this->loadResultMap($node);
363
364                 foreach($document->xpath('//parameterMap') as $node)
365                         $this->loadParameterMap($node);
366
367                 foreach($document->xpath('//statement') as $node)
368                         $this->loadStatementTag($node);
369
370                 foreach($document->xpath('//select') as $node)
371                         $this->loadSelectTag($node);
372
373                 foreach($document->xpath('//insert') as $node)
374                         $this->loadInsertTag($node);
375
376                 foreach($document->xpath('//update') as $node)
377                         $this->loadUpdateTag($node);
378
379                 foreach($document->xpath('//delete') as $node)
380                         $this->loadDeleteTag($node);
381
382                 foreach($document->xpath('//procedure') as $node)
383                         $this->loadProcedureTag($node);
384
385                 foreach($document->xpath('//cacheModel') as $node)
386                                 $this->loadCacheModel($node);
387
388                 $this->registerCacheTriggers();
389         }
390
391         /**
392          * Load the result maps.
393          * @param SimpleXmlElement result map node.
394          */
395         protected function loadResultMap($node)
396         {
397                 $resultMap = $this->createResultMap($node);
398
399                 //find extended result map.
400                 if(strlen($extendMap = $resultMap->getExtends()) > 0)
401                 {
402                         if(!$this->_manager->getResultMaps()->contains($extendMap))
403                         {
404                                 $extendNode=$this->getElementByIdValue($this->_document,'resultMap',$extendMap);
405                                 if($extendNode!==null)
406                                         $this->loadResultMap($extendNode);
407                         }
408
409                         if(!$this->_manager->getResultMaps()->contains($extendMap))
410                                 throw new TSqlMapConfigurationException(
411                                         'sqlmap_unable_to_find_parent_result_map', $node, $this->_configFile, $extendMap);
412
413                         $superMap = $this->_manager->getResultMap($extendMap);
414                         $resultMap->getColumns()->mergeWith($superMap->getColumns());
415                 }
416
417                 //add the result map
418                 if(!$this->_manager->getResultMaps()->contains($resultMap->getID()))
419                         $this->_manager->addResultMap($resultMap);
420         }
421
422         /**
423          * Create a new result map and its associated result properties,
424          * disciminiator and sub maps.
425          * @param SimpleXmlElement result map node
426          * @return TResultMap SqlMap result mapping.
427          */
428         protected function createResultMap($node)
429         {
430                 $resultMap = new TResultMap();
431                 $this->setObjectPropFromNode($resultMap,$node);
432
433                 //result nodes
434                 foreach($node->result as $result)
435                 {
436                         $property = new TResultProperty($resultMap);
437                         $this->setObjectPropFromNode($property,$result);
438                         $resultMap->addResultProperty($property);
439                 }
440
441                 //create the discriminator
442                 $discriminator = null;
443                 if(isset($node->discriminator))
444                 {
445                         $discriminator = new TDiscriminator();
446                         $this->setObjectPropFromNode($discriminator, $node->discriminator);
447                         $discriminator->initMapping($resultMap);
448                 }
449
450                 foreach($node->xpath('subMap') as $subMapNode)
451                 {
452                         if($discriminator===null)
453                                 throw new TSqlMapConfigurationException(
454                                         'sqlmap_undefined_discriminator', $node, $this->_configFile,$subMapNode);
455                         $subMap = new TSubMap;
456                         $this->setObjectPropFromNode($subMap,$subMapNode);
457                         $discriminator->addSubMap($subMap);
458                 }
459
460                 if($discriminator!==null)
461                         $resultMap->setDiscriminator($discriminator);
462
463                 return $resultMap;
464         }
465
466         /**
467          * Load parameter map from xml.
468          *
469          * @param SimpleXmlElement parameter map node.
470          */
471         protected function loadParameterMap($node)
472         {
473                 $parameterMap = $this->createParameterMap($node);
474
475                 if(strlen($extendMap = $parameterMap->getExtends()) > 0)
476                 {
477                         if(!$this->_manager->getParameterMaps()->contains($extendMap))
478                         {
479                                 $extendNode=$this->getElementByIdValue($this->_document,'parameterMap',$extendMap);
480                                 if($extendNode!==null)
481                                         $this->loadParameterMap($extendNode);
482                         }
483
484                         if(!$this->_manager->getParameterMaps()->contains($extendMap))
485                                 throw new TSqlMapConfigurationException(
486                                         'sqlmap_unable_to_find_parent_parameter_map', $node, $this->_configFile,$extendMap);
487                         $superMap = $this->_manager->getParameterMap($extendMap);
488                         $index = 0;
489                         foreach($superMap->getPropertyNames() as $propertyName)
490                                 $parameterMap->insertProperty($index++,$superMap->getProperty($propertyName));
491                 }
492                 $this->_manager->addParameterMap($parameterMap);
493         }
494
495         /**
496          * Create a new parameter map from xml node.
497          * @param SimpleXmlElement parameter map node.
498          * @return TParameterMap new parameter mapping.
499          */
500         protected function createParameterMap($node)
501         {
502                 $parameterMap = new TParameterMap();
503                 $this->setObjectPropFromNode($parameterMap,$node);
504                 foreach($node->parameter as $parameter)
505                 {
506                         $property = new TParameterProperty();
507                         $this->setObjectPropFromNode($property,$parameter);
508                         $parameterMap->addProperty($property);
509                 }
510                 return $parameterMap;
511         }
512
513         /**
514          * Load statement mapping from xml configuration file.
515          * @param SimpleXmlElement statement node.
516          */
517         protected function loadStatementTag($node)
518         {
519                 $statement = new TSqlMapStatement();
520                 $this->setObjectPropFromNode($statement,$node);
521                 $this->processSqlStatement($statement, $node);
522                 $mappedStatement = new TMappedStatement($this->_manager, $statement);
523                 $this->_manager->addMappedStatement($mappedStatement);
524         }
525
526         /**
527          * Load extended SQL statements if application. Replaces global properties
528          * in the sql text. Extracts inline parameter maps.
529          * @param TSqlMapStatement mapped statement.
530          * @param SimpleXmlElement statement node.
531          */
532         protected function processSqlStatement($statement, $node)
533         {
534                 $commandText = (string)$node;
535                 if(strlen($extend = $statement->getExtends()) > 0)
536                 {
537                         $superNode = $this->getElementByIdValue($this->_document,'*',$extend);
538                         if($superNode!==null)
539                                 $commandText = (string)$superNode . $commandText;
540                         else
541                                 throw new TSqlMapConfigurationException(
542                                                 'sqlmap_unable_to_find_parent_sql', $extend, $this->_configFile,$node);
543                 }
544                 //$commandText = $this->_xmlConfig->replaceProperties($commandText);
545                 $statement->initialize($this->_manager);
546                 $this->applyInlineParameterMap($statement, $commandText, $node);
547         }
548
549         /**
550          * Extract inline parameter maps.
551          * @param TSqlMapStatement statement object.
552          * @param string sql text
553          * @param SimpleXmlElement statement node.
554          */
555         protected function applyInlineParameterMap($statement, $sqlStatement, $node)
556         {
557                 $scope['file'] = $this->_configFile;
558                 $scope['node'] = $node;
559
560                 $sqlStatement=preg_replace(self::ESCAPED_INLINE_SYMBOL_REGEXP,self::INLINE_PLACEHOLDER,$sqlStatement);
561                 if($statement->parameterMap() === null)
562                 {
563                         // Build a Parametermap with the inline parameters.
564                         // if they exist. Then delete inline infos from sqltext.
565                         $parameterParser = new TInlineParameterMapParser;
566                         $sqlText = $parameterParser->parse($sqlStatement, $scope);
567                         if(count($sqlText['parameters']) > 0)
568                         {
569                                 $map = new TParameterMap();
570                                 $map->setID($statement->getID().'-InLineParameterMap');
571                                 $statement->setInlineParameterMap($map);
572                                 foreach($sqlText['parameters'] as $property)
573                                         $map->addProperty($property);
574                         }
575                         $sqlStatement = $sqlText['sql'];
576                 }
577                 $sqlStatement=preg_replace('/'.self::INLINE_PLACEHOLDER.'/',self::INLINE_SYMBOL,$sqlStatement);
578
579                 $this->prepareSql($statement, $sqlStatement, $node);
580         }
581
582         /**
583          * Prepare the sql text (may extend to dynamic sql).
584          * @param TSqlMapStatement mapped statement.
585          * @param string sql text.
586          * @param SimpleXmlElement statement node.
587          * @todo Extend to dynamic sql.
588          */
589         protected function prepareSql($statement,$sqlStatement, $node)
590         {
591                 $simpleDynamic = new TSimpleDynamicParser;
592                 $sqlStatement=preg_replace(self::ESCAPED_SIMPLE_MARK_REGEXP,self::SIMPLE_PLACEHOLDER,$sqlStatement);
593                 $dynamics = $simpleDynamic->parse($sqlStatement);
594                 if(count($dynamics['parameters']) > 0)
595                 {
596                         $sql = new TSimpleDynamicSql($dynamics['parameters']);
597                         $sqlStatement = $dynamics['sql'];
598                 }
599                 else
600                         $sql = new TStaticSql();
601                 $sqlStatement=preg_replace('/'.self::SIMPLE_PLACEHOLDER.'/',self::SIMPLE_MARK,$sqlStatement);
602                 $sql->buildPreparedStatement($statement, $sqlStatement);
603                 $statement->setSqlText($sql);
604         }
605
606         /**
607          * Load select statement from xml mapping.
608          * @param SimpleXmlElement select node.
609          */
610         protected function loadSelectTag($node)
611         {
612                 $select = new TSqlMapSelect;
613                 $this->setObjectPropFromNode($select,$node);
614                 $this->processSqlStatement($select,$node);
615                 $mappedStatement = new TMappedStatement($this->_manager, $select);
616                 if(strlen($select->getCacheModel()) > 0)
617                         $mappedStatement = new TCachingStatement($mappedStatement);
618
619                 $this->_manager->addMappedStatement($mappedStatement);
620         }
621
622         /**
623          * Load insert statement from xml mapping.
624          * @param SimpleXmlElement insert node.
625          */
626         protected function loadInsertTag($node)
627         {
628                 $insert = $this->createInsertStatement($node);
629                 $this->processSqlStatement($insert, $node);
630                 $mappedStatement = new TInsertMappedStatement($this->_manager, $insert);
631                 $this->_manager->addMappedStatement($mappedStatement);
632         }
633
634         /**
635          * Create new insert statement from xml node.
636          * @param SimpleXmlElement insert node.
637          * @return TSqlMapInsert insert statement.
638          */
639         protected function createInsertStatement($node)
640         {
641                 $insert = new TSqlMapInsert;
642                 $this->setObjectPropFromNode($insert,$node);
643                 if(isset($node->selectKey))
644                         $this->loadSelectKeyTag($insert,$node->selectKey);
645                 return $insert;
646         }
647
648         /**
649          * Load the selectKey statement from xml mapping.
650          * @param SimpleXmlElement selectkey node
651          */
652         protected function loadSelectKeyTag($insert, $node)
653         {
654                 $selectKey = new TSqlMapSelectKey;
655                 $this->setObjectPropFromNode($selectKey,$node);
656                 $selectKey->setID($insert->getID());
657                 $selectKey->setID($insert->getID().'.SelectKey');
658                 $this->processSqlStatement($selectKey,$node);
659                 $insert->setSelectKey($selectKey);
660                 $mappedStatement = new TMappedStatement($this->_manager, $selectKey);
661                 $this->_manager->addMappedStatement($mappedStatement);
662         }
663
664         /**
665          * Load update statement from xml mapping.
666          * @param SimpleXmlElement update node.
667          */
668         protected function loadUpdateTag($node)
669         {
670                 $update = new TSqlMapUpdate;
671                 $this->setObjectPropFromNode($update,$node);
672                 $this->processSqlStatement($update, $node);
673                 $mappedStatement = new TUpdateMappedStatement($this->_manager, $update);
674                 $this->_manager->addMappedStatement($mappedStatement);
675         }
676
677         /**
678          * Load delete statement from xml mapping.
679          * @param SimpleXmlElement delete node.
680          */
681         protected function loadDeleteTag($node)
682         {
683                 $delete = new TSqlMapDelete;
684                 $this->setObjectPropFromNode($delete,$node);
685                 $this->processSqlStatement($delete, $node);
686                 $mappedStatement = new TDeleteMappedStatement($this->_manager, $delete);
687                 $this->_manager->addMappedStatement($mappedStatement);
688         }
689
690         /**
691          * Load procedure statement from xml mapping.
692          * @todo Implement loading procedure
693          * @param SimpleXmlElement procedure node
694          */
695         protected function loadProcedureTag($node)
696         {
697                 //var_dump('todo: add load procedure');
698         }
699
700         /**
701          * Load cache models from xml mapping.
702          * @param SimpleXmlElement cache node.
703          */
704         protected function loadCacheModel($node)
705         {
706                 $cacheModel = new TSqlMapCacheModel;
707                 $properties = array('id','implementation');
708                 foreach($node->attributes() as $name=>$value)
709                 {
710                         if(in_array(strtolower($name), $properties))
711                                 $cacheModel->{'set'.$name}((string)$value);
712                 }
713                 $cache = Prado::createComponent($cacheModel->getImplementationClass(), $cacheModel);
714                 $this->setObjectPropFromNode($cache,$node,$properties);
715
716                 foreach($node->xpath('property') as $propertyNode)
717                 {
718                         $name = $propertyNode->attributes()->name;
719                         if($name===null || $name==='') continue;
720
721                         $value = $propertyNode->attributes()->value;
722                         if($value===null || $value==='') continue;
723
724                         if( !TPropertyAccess::has($cache, $name) ) continue;
725
726                         TPropertyAccess::set($cache, $name, $value);
727                 }
728
729                 $this->loadFlushInterval($cacheModel,$node);
730
731                 $cacheModel->initialize($cache);
732                 $this->_manager->addCacheModel($cacheModel);
733                 foreach($node->xpath('flushOnExecute') as $flush)
734                         $this->loadFlushOnCache($cacheModel,$node,$flush);
735         }
736
737         /**
738          * Load the flush interval
739          * @param TSqlMapCacheModel cache model
740          * @param SimpleXmlElement cache node
741          */
742         protected function loadFlushInterval($cacheModel, $node)
743         {
744                 $flushInterval = $node->xpath('flushInterval');
745                 if($flushInterval === null || count($flushInterval) === 0) return;
746                 $duration = 0;
747                 foreach($flushInterval[0]->attributes() as $name=>$value)
748                 {
749                         switch(strToLower($name))
750                         {
751                                 case 'seconds':
752                                         $duration += (integer)$value;
753                                 break;
754                                 case 'minutes':
755                                         $duration += 60 * (integer)$value;
756                                 break;
757                                 case 'hours':
758                                         $duration += 3600 * (integer)$value;
759                                 break;
760                                 case 'days':
761                                         $duration += 86400 * (integer)$value;
762                                 break;
763                                 case 'duration':
764                                         $duration = (integer)$value;
765                                 break 2; // switch, foreach
766                         }
767                 }
768                 $cacheModel->setFlushInterval($duration);
769         }
770
771         /**
772          * Load the flush on cache properties.
773          * @param TSqlMapCacheModel cache model
774          * @param SimpleXmlElement parent node.
775          * @param SimpleXmlElement flush node.
776          */
777         protected function loadFlushOnCache($cacheModel,$parent,$node)
778         {
779                 $id = $cacheModel->getID();
780                 if(!isset($this->_FlushOnExecuteStatements[$id]))
781                         $this->_FlushOnExecuteStatements[$id] = array();
782                 foreach($node->attributes() as $name=>$value)
783                 {
784                         if(strtolower($name)==='statement')
785                                 $this->_FlushOnExecuteStatements[$id][] = (string)$value;
786                 }
787         }
788
789         /**
790          * Attach CacheModel to statement and register trigger statements for cache models
791          */
792         protected function registerCacheTriggers()
793         {
794                 foreach($this->_FlushOnExecuteStatements as $cacheID => $statementIDs)
795                 {
796                         $cacheModel = $this->_manager->getCacheModel($cacheID);
797                         foreach($statementIDs as $statementID)
798                         {
799                                 $statement = $this->_manager->getMappedStatement($statementID);
800                                 $cacheModel->registerTriggerStatement($statement);
801                         }
802                 }
803         }
804 }
805