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