PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/src/main/php/xp/codegen/dataset/Generator.class.php

http://github.com/xp-framework/xp-framework
PHP | 205 lines | 111 code | 24 blank | 70 comment | 10 complexity | eaf1fc0d03955a547c96c96fd7cd7eea MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /* This class is part of the XP framework
  3. *
  4. * $Id$
  5. */
  6. $package= 'xp.codegen.dataset';
  7. uses(
  8. 'xp.codegen.AbstractGenerator',
  9. 'rdbms.DSN',
  10. 'rdbms.DBTable',
  11. 'rdbms.DriverManager',
  12. 'rdbms.util.DBConstraintXmlGenerator',
  13. 'rdbms.util.DBXMLNamingContext',
  14. 'rdbms.util.DBXmlGenerator',
  15. 'xml.DomXSLProcessor',
  16. 'lang.XPClass'
  17. );
  18. /**
  19. * DataSet
  20. * =======
  21. * Generates rdbms.DataSet classes for use in the XP framework's O/R mapper.
  22. *
  23. * Usage:
  24. * <pre>
  25. * $ cgen ... dataset {dsn} [-p {package}] [-h {host}] [-l {language}] [-n {nstrategy}] [-pv {prefix} [-pt {ptargets}] [-pe {pexclude}]]
  26. * </pre>
  27. *
  28. * Options
  29. * -------
  30. * <ul>
  31. * <li>package: The package name, default "db"</li>
  32. * <li>host: Which connection name to use, defaults to host name from DSN</li>
  33. * <li>language: Language to generate, defaults to "xp5"</li>
  34. * <li>prefix: Prefix to add to the class name, defaults to ""</li>
  35. * <li>ptargets: List of table names to use with prefix separated by the pipe symbol "|", defaults to ""</li>
  36. * <li>pexclude: Mode ptargets are treated - if pexclude is TRUE ptargets are treated as blacklist else as whitelist, defaults to FALSE</li>
  37. * <li>nstrategy: strategy to name constraints, defaults to rdbms.util.DBXMLNamingStrategyDefault</li>
  38. * </ul>
  39. *
  40. * Languages
  41. * ---------
  42. * The following languages are supported: xp5, xp4
  43. *
  44. * @purpose Code generator
  45. */
  46. class xp?codegen?dataset?Generator extends AbstractGenerator {
  47. const
  48. CONSTRAINT_FILE_NAME= '__Constraints';
  49. protected static
  50. $adapters = array();
  51. protected
  52. $host = NULL,
  53. $prefix = NULL,
  54. $ptargets = NULL,
  55. $pexclude = NULL,
  56. $adapter = NULL,
  57. $processor= NULL,
  58. $package = '',
  59. $naming = '';
  60. static function __static() {
  61. self::$adapters['mysql']= XPClass::forName('rdbms.mysql.MySQLDBAdapter');
  62. self::$adapters['sqlite']= XPClass::forName('rdbms.sqlite.SQLiteDBAdapter');
  63. self::$adapters['pgsql']= XPClass::forName('rdbms.pgsql.PostgreSQLDBAdapter');
  64. self::$adapters['sybase']= XPClass::forName('rdbms.sybase.SybaseDBAdapter');
  65. }
  66. /**
  67. * Constructor
  68. *
  69. * @param util.cmd.ParamString args
  70. */
  71. public function __construct(ParamString $args) {
  72. $dsn= new DSN($args->value(0));
  73. $this->adapter= self::$adapters[$dsn->getDriver()]->newInstance(
  74. DriverManager::getInstance()->getConnection($dsn->dsn)
  75. );
  76. $this->package= $args->value('package', 'p', 'db');
  77. $this->host= $args->value('host', 'h', $dsn->getHost());
  78. $this->naming= $args->value('nstrategy', 'n', '');
  79. if ('' != $this->naming) DBXMLNamingContext::setStrategy(XPClass::forName($this->naming)->newInstance());
  80. $this->prefix= $args->value('prefix', 'pv', '');
  81. $this->ptargets= explode('|', $args->value('ptargets', 'pt', ''));
  82. $this->pexclude= $args->value('pexclude', 'pe', FALSE);
  83. // Setup generator
  84. $this->processor= new DomXSLProcessor();
  85. $this->processor->setXSLBuf($this->getClass()->getPackage()->getResource($args->value('lang', 'l', 'xp5.php').'.xsl'));
  86. $this->processor->setParam('package', $this->package);
  87. if ($this->prefix) {
  88. $this->processor->setParam('prefix', $this->prefix);
  89. $this->processor->setParam($this->pexclude ? 'exprefix' : 'incprefix', implode(',', $this->ptargets));
  90. }
  91. }
  92. /**
  93. * Connect the database
  94. *
  95. */
  96. #[@target]
  97. public function connect() {
  98. $this->adapter->conn->connect();
  99. }
  100. /**
  101. * Fetch tables
  102. *
  103. */
  104. #[@target(depends= 'connect')]
  105. public function fetchTables() {
  106. return DBTable::getByDatabase(
  107. $this->adapter,
  108. $this->adapter->conn->dsn->getDatabase()
  109. );
  110. }
  111. /**
  112. * Fetch constraints
  113. *
  114. */
  115. #[@target(depends= 'connect')]
  116. public function fetchConstraints() {
  117. return DBConstraintXmlGenerator::createFromDatabase(
  118. $this->adapter,
  119. $this->adapter->conn->dsn->getDatabase()
  120. )->getTree();
  121. }
  122. /**
  123. * Generate XML from the tables
  124. *
  125. */
  126. #[@target(input= array('fetchTables', 'fetchConstraints', 'storage'))]
  127. public function generateTableXml($tables, $constraints, $storage) {
  128. $xml= array();
  129. foreach ($tables as $table) {
  130. // Calculate classname
  131. $className= ucfirst($table->name);
  132. if (isset($this->prefix)) {
  133. switch (1) {
  134. case (FALSE == $this->ptargets):
  135. case (in_array($table->name, $this->ptargets) && FALSE == $this->pexclude):
  136. case (!in_array($table->name, $this->ptargets) && TRUE == $this->pexclude):
  137. $className= $this->prefix.$className;
  138. break;
  139. }
  140. }
  141. $gen= DBXmlGenerator::createFromTable(
  142. $table,
  143. $this->host,
  144. $this->adapter->conn->dsn->getDatabase()
  145. )->getTree();
  146. // Add extra information
  147. with ($node= $gen->root->children[0]); {
  148. $node->setAttribute('dbtype', $this->adapter->conn->dsn->getDriver());
  149. $node->setAttribute('class', $className);
  150. $node->setAttribute('package', $this->package);
  151. }
  152. $xml[]= $storage->write($className, $gen->getSource(INDENT_DEFAULT));
  153. }
  154. $storage->write(self::CONSTRAINT_FILE_NAME, $constraints->getSource(INDENT_DEFAULT));
  155. return $xml;
  156. }
  157. /**
  158. * Apply XSLT stylesheet and generate sourcecode
  159. *
  160. */
  161. #[@target(input= array('generateTableXml', 'output'))]
  162. public function generateCode($tables, $output) {
  163. $dir= strtr($this->package, '.', '/').'/';
  164. $this->processor->setParam('definitionpath', $this->storage->getUri());
  165. $this->processor->setParam('constraintfile', $this->storage->getUri().self::CONSTRAINT_FILE_NAME);
  166. foreach ($tables as $stored) {
  167. $this->processor->setXMLBuf($stored->data());
  168. $this->processor->run();
  169. $output->append($dir.$stored->name().xp::CLASS_FILE_EXT, $this->processor->output());
  170. }
  171. }
  172. /**
  173. * Creates a string representation of this generator
  174. *
  175. * @return string
  176. */
  177. public function toString() {
  178. return $this->getClassName().'['.$this->adapter->conn->dsn->toString().']';
  179. }
  180. }
  181. ?>