[ Index ] |
|
Code source de Symfony 1.0.0 |
1 <?php 2 3 /* 4 * $Id: XmlToAppData.php 337 2006-02-15 14:41:54Z hans $ 5 * 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 7 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 8 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 9 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 10 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 12 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 13 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 14 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 15 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 16 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17 * 18 * This software consists of voluntary contributions made by many individuals 19 * and is licensed under the LGPL. For more information please see 20 * <http://propel.phpdb.org>. 21 */ 22 23 include_once 'propel/engine/database/model/AppData.php'; 24 25 // Phing dependencies 26 require_once 'phing/parser/AbstractHandler.php'; 27 include_once 'phing/system/io/FileReader.php'; 28 29 /** 30 * A class that is used to parse an input xml schema file and creates an AppData 31 * PHP object. 32 * 33 * @author Hans Lellelid <hans@xmpl.org> (Propel) 34 * @author Leon Messerschmidt <leon@opticode.co.za> (Torque) 35 * @author Jason van Zyl <jvanzyl@apache.org> (Torque) 36 * @author Martin Poeschl <mpoeschl@marmot.at> (Torque) 37 * @author Daniel Rall <dlr@collab.net> (Torque) 38 * @version $Revision: 337 $ 39 * @package propel.engine.database.transform 40 */ 41 class XmlToAppData extends AbstractHandler { 42 43 /** enables debug output */ 44 const DEBUG = false; 45 46 private $app; 47 private $platform; 48 private $currDB; 49 private $currTable; 50 private $currColumn; 51 private $currFK; 52 private $currIndex; 53 private $currUnique; 54 private $currValidator; 55 private $currVendorObject; 56 57 private $isForReferenceOnly; 58 private $currentPackage; 59 private $currentXmlFile; 60 private $defaultPackage; 61 62 private $encoding; 63 64 /** two-dimensional array, 65 first dimension is for schemas(key is the path to the schema file), 66 second is for tags within the schema */ 67 private $schemasTagsStack = array(); 68 69 public $parser; 70 71 /** 72 * Creates a new instance for the specified database type. 73 * 74 * @param Platform $platform The type of database for the application. 75 * @param string $defaultPackage the default PHP package used for the om 76 * @param string $encoding The database encoding. 77 */ 78 public function __construct(Platform $platform, $defaultPackage, $encoding = 'iso-8859-1') 79 { 80 $this->app = new AppData($platform); 81 $this->platform = $platform; 82 $this->defaultPackage = $defaultPackage; 83 $this->firstPass = true; 84 $this->encoding = $encoding; 85 } 86 87 /** 88 * Parses a XML input file and returns a newly created and 89 * populated AppData structure. 90 * 91 * @param string $xmlFile The input file to parse. 92 * @return AppData populated by <code>xmlFile</code>. 93 */ 94 public function parseFile($xmlFile) 95 { 96 // we don't want infinite recursion 97 if($this->isAlreadyParsed($xmlFile)) { 98 return; 99 } 100 101 $domDocument = new DomDocument('1.0', 'UTF-8'); 102 $domDocument->load($xmlFile); 103 104 // store current schema file path 105 $this->schemasTagsStack[$xmlFile] = array(); 106 107 $this->currentXmlFile = $xmlFile; 108 109 try { 110 $fr = new FileReader($xmlFile); 111 } catch (Exception $e) { 112 $f = new PhingFile($xmlFile); 113 throw new Exception("XML File not found: " . $f->getAbsolutePath()); 114 } 115 116 $br = new BufferedReader($fr); 117 118 $this->parser = new ExpatParser($br); 119 $this->parser->parserSetOption(XML_OPTION_CASE_FOLDING, 0); 120 $this->parser->setHandler($this); 121 122 try { 123 $this->parser->parse(); 124 } catch (Exception $e) { 125 $br->close(); 126 throw $e; 127 } 128 $br->close(); 129 130 array_pop($this->schemasTagsStack); 131 132 return $this->app; 133 } 134 135 /** 136 * Handles opening elements of the xml file. 137 * 138 * @param string $uri 139 * @param string $localName The local name (without prefix), or the empty string if 140 * Namespace processing is not being performed. 141 * @param string $rawName The qualified name (with prefix), or the empty string if 142 * qualified names are not available. 143 * @param string $attributes The specified or defaulted attributes 144 */ 145 public function startElement($name, $attributes) { 146 147 try { 148 149 $parentTag = $this->peekCurrentSchemaTag(); 150 151 if ($parentTag === false) { 152 153 switch($name) { 154 case "database": 155 if ($this->isExternalSchema()) { 156 $this->currentPackage = @$attributes["package"]; 157 if ($this->currentPackage === null) { 158 $this->currentPackage = $this->defaultPackage; 159 } 160 } else { 161 $this->currDB = $this->app->addDatabase($attributes); 162 } 163 break; 164 165 default: 166 $this->_throwInvalidTagException($name); 167 } 168 169 } elseif ($parentTag == "database") { 170 171 switch($name) { 172 173 case "external-schema": 174 $xmlFile = @$attributes["filename"]; 175 176 //"referenceOnly" attribute is valid in the main schema XML file only, 177 //and it's ingnored in the nested external-schemas 178 if(!$this->isExternalSchema()) { 179 $isForRefOnly = @$attributes["referenceOnly"]; 180 $this->isForReferenceOnly = ($isForRefOnly !== null ? (strtolower($isForRefOnly) === "true") : true); // defaults to TRUE 181 } 182 183 if ($xmlFile{0} != '/') { 184 $f = new PhingFile($this->currentXmlFile); 185 $xf = new PhingFile($f->getParent(), $xmlFile); 186 $xmlFile = $xf->getPath(); 187 } 188 189 $this->parseFile($xmlFile); 190 break; 191 192 case "domain": 193 $this->currDB->addDomain($attributes); 194 break; 195 196 case "table": 197 $this->currTable = $this->currDB->addTable($attributes); 198 if ($this->isExternalSchema()) { 199 $this->currTable->setForReferenceOnly($this->isForReferenceOnly); 200 $this->currTable->setPackage($this->currentPackage); 201 } 202 break; 203 204 case "vendor": 205 $this->currVendorObject = new ObjectWithVendorSpecificData($this->currDB, $attributes['type']); 206 break; 207 208 default: 209 $this->_throwInvalidTagException($name); 210 } 211 212 } elseif ($parentTag == "table") { 213 214 switch($name) { 215 case "column": 216 $this->currColumn = $this->currTable->addColumn($attributes); 217 break; 218 219 case "foreign-key": 220 $this->currFK = $this->currTable->addForeignKey($attributes); 221 break; 222 223 case "index": 224 $this->currIndex = $this->currTable->addIndex($attributes); 225 break; 226 227 case "unique": 228 $this->currUnique = $this->currTable->addUnique($attributes); 229 break; 230 231 case "vendor": 232 $this->currVendorObject = new ObjectWithVendorSpecificData($this->currTable, $attributes['type']); 233 break; 234 235 case "validator": 236 $this->currValidator = $this->currTable->addValidator($attributes); 237 break; 238 239 case "id-method-parameter": 240 $this->currTable->addIdMethodParameter($attributes); 241 break; 242 243 default: 244 $this->_throwInvalidTagException($name); 245 } 246 247 } elseif ($parentTag == "column") { 248 249 switch($name) { 250 case "inheritance": 251 $this->currColumn->addInheritance($attributes); 252 break; 253 254 case "vendor": 255 $this->currVendorObject = new ObjectWithVendorSpecificData($this->currColumn, $attributes['type']); 256 break; 257 258 default: 259 $this->_throwInvalidTagException($name); 260 } 261 262 } elseif ($parentTag == "foreign-key") { 263 264 switch($name) { 265 case "reference": 266 $this->currFK->addReference($attributes); 267 break; 268 269 case "vendor": 270 $this->currVendorObject = new ObjectWithVendorSpecificData($this->currFK, $attributes['type']); 271 break; 272 273 default: 274 $this->_throwInvalidTagException($name); 275 } 276 277 } elseif ($parentTag == "index") { 278 279 switch($name) { 280 case "index-column": 281 $this->currIndex->addColumn($attributes); 282 break; 283 284 case "vendor": 285 $this->currVendorObject = new ObjectWithVendorSpecificData($this->currIndex, $attributes['type']); 286 break; 287 288 default: 289 $this->_throwInvalidTagException($name); 290 } 291 292 } elseif ($parentTag == "unique") { 293 294 switch($name) { 295 case "unique-column": 296 $this->currUnique->addColumn($attributes); 297 break; 298 299 case "vendor": 300 $this->currVendorObject = new ObjectWithVendorSpecificData($this->currUnique, $attributes['type']); 301 break; 302 303 default: 304 $this->_throwInvalidTagException($name); 305 } 306 } elseif ($parentTag == "validator") { 307 switch($name) { 308 case "rule": 309 $this->currValidator->addRule($attributes); 310 break; 311 default: 312 $this->_throwInvalidTagException($name); 313 } 314 } elseif ($parentTag == "vendor") { 315 316 switch($name) { 317 case "parameter": 318 if($this->currVendorObject->isCompatible($this->platform->getDatabaseType())) { 319 $this->currVendorObject->setVendorParameter($attributes['name'], iconv('utf-8',$this->encoding, $attributes['value'])); 320 } 321 break; 322 323 default: 324 $this->_throwInvalidTagException($name); 325 } 326 327 } else { 328 // it must be an invalid tag 329 $this->_throwInvalidTagException($name); 330 } 331 332 $this->pushCurrentSchemaTag($name); 333 334 } catch (BuildException $e) { 335 throw $e; 336 } catch (Exception $e) { 337 echo $e; 338 echo "\n"; 339 throw $e; 340 } 341 } 342 343 function _throwInvalidTagException($tag_name) 344 { 345 throw new BuildException("Unexpected tag <" . $tag_name . ">", $this->parser->getLocation()); 346 } 347 348 /** 349 * Handles closing elements of the xml file. 350 * 351 * @param uri 352 * @param localName The local name (without prefix), or the empty string if 353 * Namespace processing is not being performed. 354 * @param rawName The qualified name (with prefix), or the empty string if 355 * qualified names are not available. 356 */ 357 public function endElement($name) 358 { 359 if (self::DEBUG) { 360 print("endElement(" . $name . ") called\n"); 361 } 362 363 $this->popCurrentSchemaTag(); 364 } 365 366 protected function peekCurrentSchemaTag() 367 { 368 $keys = array_keys($this->schemasTagsStack); 369 return end($this->schemasTagsStack[end($keys)]); 370 } 371 372 protected function popCurrentSchemaTag() 373 { 374 $keys = array_keys($this->schemasTagsStack); 375 array_pop($this->schemasTagsStack[end($keys)]); 376 } 377 378 protected function pushCurrentSchemaTag($tag) 379 { 380 $keys = array_keys($this->schemasTagsStack); 381 $this->schemasTagsStack[end($keys)][] = $tag; 382 } 383 384 protected function isExternalSchema() 385 { 386 return (sizeof($this->schemasTagsStack) > 1); 387 } 388 389 protected function isAlreadyParsed($filePath) 390 { 391 return isset($this->schemasTagsStack[$filePath]); 392 } 393 } 394 395 /** 396 * Utility class used for objects with vendor data. 397 * 398 * @package propel.engine.database.transform 399 */ 400 class ObjectWithVendorSpecificData 401 { 402 protected $object; 403 protected $vendorType; 404 405 public function __construct($object, $vendorType) 406 { 407 $this->object = $object; 408 $this->vendorType = $vendorType; 409 } 410 411 public function isCompatible($type) 412 { 413 return ($this->vendorType == $type); 414 } 415 416 public function setVendorParameter($name, $value) 417 { 418 $this->object->setVendorParameter($name, $value); 419 } 420 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Mar 16 22:42:14 2007 | par Balluche grâce à PHPXref 0.7 |