diff --git a/lib/Doctrine/TODO/AuditLog/Listener.php b/lib/Doctrine/TODO/AuditLog/Listener.php
new file mode 100644
index 000000000..dcea2a9d6
--- /dev/null
+++ b/lib/Doctrine/TODO/AuditLog/Listener.php
@@ -0,0 +1,91 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+Doctrine::autoload('Doctrine_Record_Listener');
+/**
+ * Doctrine_AuditLog_Listener
+ *
+ * @package     Doctrine
+ * @subpackage  AuditLog
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_AuditLog_Listener extends Doctrine_Record_Listener
+{
+    
+    protected $_auditLog;
+
+    public function __construct(Doctrine_AuditLog $auditLog) 
+    {
+        $this->_auditLog = $auditLog;
+    }
+
+    public function preInsert(Doctrine_Event $event)
+    {
+        $versionColumn = $this->_auditLog->getOption('versionColumn');
+
+        $event->getInvoker()->set($versionColumn, 1);
+    }
+
+    public function postInsert(Doctrine_Event $event) 
+    {
+        $class = $this->_auditLog->getOption('className');
+
+        $record  = $event->getInvoker();
+        $version = new $class();
+        $version->merge($record->toArray());
+        $version->save();
+    }
+
+    public function preDelete(Doctrine_Event $event)
+    {
+        $class = $this->_auditLog->getOption('className');
+
+        $record  = $event->getInvoker();
+
+        $versionColumn = $this->_auditLog->getOption('versionColumn');
+        $version = $record->get($versionColumn);
+
+        $record->set($versionColumn, ++$version);
+
+        $version = new $class();
+        $version->merge($record->toArray());
+        $version->save();
+    }
+
+    public function preUpdate(Doctrine_Event $event)
+    {
+        $class  = $this->_auditLog->getOption('className');
+        $record = $event->getInvoker(); 
+
+        $versionColumn = $this->_auditLog->getOption('versionColumn');
+
+        $version = $record->get($versionColumn);
+
+        $record->set($versionColumn, ++$version);
+        
+        $version = new $class();
+        $version->merge($record->toArray());
+        $version->save();
+    }
+}
diff --git a/lib/Doctrine/TODO/Builder/Exception.php b/lib/Doctrine/TODO/Builder/Exception.php
new file mode 100644
index 000000000..c8728ce7e
--- /dev/null
+++ b/lib/Doctrine/TODO/Builder/Exception.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: Exception.php 3570 2008-01-22 22:52:53Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+Doctrine::autoload('Doctrine_Exception');
+/**
+ * @package     Doctrine
+ * @subpackage  Import
+ * @url         http://www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @author      Jukka Hassinen <Jukka.Hassinen@BrainAlliance.com>
+ * @version     $Id: Exception.php 3570 2008-01-22 22:52:53Z jwage $
+ */
+
+/**
+ * Doctrine_Builder_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Builder
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 3570 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jonwage@gmail.com>
+ */
+class Doctrine_Builder_Exception extends Doctrine_Exception
+{
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Builder/Migration.php b/lib/Doctrine/TODO/Builder/Migration.php
new file mode 100644
index 000000000..c5dff41bd
--- /dev/null
+++ b/lib/Doctrine/TODO/Builder/Migration.php
@@ -0,0 +1,299 @@
+<?php
+/*
+ *  $Id: Builder.php 2939 2007-10-19 14:23:42Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Builder_Migration
+ *
+ * @package     Doctrine
+ * @subpackage  Builder
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2939 $
+ */
+class Doctrine_Builder_Migration extends Doctrine_Builder
+{
+    /**
+     * migrationsPath
+     *
+     * The path to your migration classes directory
+     *
+     * @var string
+     */
+    private $_migrationsPath = '';
+
+    /**
+     * suffix
+     *
+     * File suffix to use when writing class definitions
+     *
+     * @var string $suffix
+     */
+    private $_suffix = '.class.php';
+
+    /**
+     * tpl
+     *
+     * Class template used for writing classes
+     *
+     * @var $_tpl
+     */
+    private static $_tpl;
+
+    /**
+     * __construct
+     *
+     * @return void
+     */
+    public function __construct($migrationsPath = null)
+    {
+        if ($migrationsPath) {
+            $this->setMigrationsPath($migrationsPath);
+        }
+
+        $this->_loadTemplate();
+    }
+
+    /**
+     * setMigrationsPath
+     *
+     * @param string path   the path where migration classes are stored and being generated
+     * @return
+     */
+    public function setMigrationsPath($path)
+    {
+        Doctrine_Lib::makeDirectories($path);
+
+        $this->_migrationsPath = $path;
+    }
+
+    /**
+     * getMigrationsPath
+     *
+     * @return string       the path where migration classes are stored and being generated
+     */
+    public function getMigrationsPath()
+    {
+        return $this->_migrationsPath;
+    }
+
+    /**
+     * loadTemplate
+     *
+     * Loads the class template used for generating classes
+     *
+     * @return void
+     */
+    protected function _loadTemplate()
+    {
+        if (isset(self::$_tpl)) {
+            return;
+        }
+
+        self::$_tpl =<<<END
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+class %s extends %s
+{
+	public function up()
+	{
+%s
+	}
+
+	public function down()
+	{
+%s
+	}
+}
+END;
+    }
+
+    /**
+     * generateMigrationsFromDb
+     *
+     * @return void
+     */
+    public function generateMigrationsFromDb()
+    {
+        $directory = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'tmp_doctrine_models';
+
+        Doctrine::generateModelsFromDb($directory);
+
+        $result = $this->generateMigrationsFromModels($directory);
+
+        Doctrine_Lib::removeDirectories($directory);
+
+        return $result;
+    }
+
+    /**
+     * generateMigrationsFromModels
+     *
+     * @param string $modelsPath
+     * @return void
+     */
+    public function generateMigrationsFromModels($modelsPath = null)
+    {
+        if ($modelsPath) {
+            $models = Doctrine::loadModels($modelsPath);
+        } else {
+            $models = Doctrine::getLoadedModels();
+        }
+
+        $foreignKeys = array();
+
+        foreach ($models as $model) {
+            $export = Doctrine::getTable($model)->getExportableFormat();
+
+            $foreignKeys[$export['tableName']] = $export['options']['foreignKeys'];
+
+            $up = $this->buildCreateTable($export);
+            $down = $this->buildDropTable($export);
+
+            $className = 'Add' . Doctrine::classify($export['tableName']);
+
+            $this->generateMigrationClass($className, array(), $up, $down);
+        }
+
+        $className = 'ApplyForeignKeyConstraints';
+
+        $up = '';
+        $down = '';
+        foreach ($foreignKeys as $tableName => $definitions)    {
+            $tableForeignKeyNames[$tableName] = array();
+
+            foreach ($definitions as $definition) {
+                $definition['name'] = $tableName . '_' . $definition['foreignTable'] . '_' . $definition['local'] . '_' . $definition['foreign'];
+
+                $up .= $this->buildCreateForeignKey($tableName, $definition);
+                $down .= $this->buildDropForeignKey($tableName, $definition);
+            }
+        }
+
+        $this->generateMigrationClass($className, array(), $up, $down);
+
+        return true;
+    }
+
+    /**
+     * buildCreateForeignKey
+     *
+     * @param string $tableName
+     * @param string $definition
+     * @return void
+     */
+    public function buildCreateForeignKey($tableName, $definition)
+    {
+        return "\t\t\$this->createForeignKey('" . $tableName . "', " . var_export($definition, true) . ");";
+    }
+
+    /**
+     * buildDropForeignKey
+     *
+     * @param string $tableName
+     * @param string $definition
+     * @return void
+     */
+    public function buildDropForeignKey($tableName, $definition)
+    {
+        return "\t\t\$this->dropForeignKey('" . $tableName . "', '" . $definition['name'] . "');\n";
+    }
+
+    /**
+     * buildCreateTable
+     *
+     * @param string $tableData
+     * @return void
+     */
+    public function buildCreateTable($tableData)
+    {
+        $code  = "\t\t\$this->createTable('" . $tableData['tableName'] . "', ";
+
+        $code .= var_export($tableData['columns'], true) . ", ";
+
+        $code .= var_export(array('indexes' => $tableData['options']['indexes'], 'primary' => $tableData['options']['primary']), true);
+
+        $code .= ");";
+
+        return $code;
+    }
+
+    /**
+     * buildDropTable
+     *
+     * @param string $tableData
+     * @return string
+     */
+    public function buildDropTable($tableData)
+    {
+        return "\t\t\$this->dropTable('" . $tableData['tableName'] . "');";
+    }
+
+    /**
+     * generateMigrationClass
+     *
+     * @return void
+     */
+    public function generateMigrationClass($className, $options = array(), $up = null, $down = null, $return = false)
+    {
+        if ($return || !$this->getMigrationsPath()) {
+            return $this->buildMigrationClass($className, null, $options, $up, $down);
+        } else {
+            if ( ! $this->getMigrationsPath()) {
+                throw new Doctrine_Migration_Exception('You must specify the path to your migrations.');
+            }
+
+            $migration = new Doctrine_Migration($this->getMigrationsPath());
+            $next = (string) $migration->getNextVersion();
+
+            $fileName = str_repeat('0', (3 - strlen($next))) . $next . '_' . Doctrine::tableize($className) . $this->_suffix;
+
+            $class = $this->buildMigrationClass($className, $fileName, $options, $up, $down);
+
+            $path = $this->getMigrationsPath() . DIRECTORY_SEPARATOR . $fileName;
+
+            file_put_contents($path, $class);
+        }
+    }
+
+    /**
+     * buildMigrationClass
+     *
+     * @return string
+     */
+    public function buildMigrationClass($className, $fileName = null, $options = array(), $up = null, $down = null)
+    {
+        $extends = isset($options['extends']) ? $options['extends']:'Doctrine_Migration';
+
+        $content  = '<?php' . PHP_EOL;
+
+        $content .= sprintf(self::$_tpl, $className,
+                                       $extends,
+                                       $up,
+                                       $down);
+
+
+        return $content;
+    }
+}
diff --git a/lib/Doctrine/TODO/Builder/Record.php b/lib/Doctrine/TODO/Builder/Record.php
new file mode 100644
index 000000000..678e45b75
--- /dev/null
+++ b/lib/Doctrine/TODO/Builder/Record.php
@@ -0,0 +1,808 @@
+<?php
+/*
+ *  $Id: Record.php 4866 2008-08-31 18:27:16Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Builder_Record
+ *
+ * Import builder is responsible of building Doctrine_Entity classes
+ * based on a database schema.
+ *
+ * @package     Doctrine
+ * @subpackage  Builder
+ * @link        www.phpdoctrine.org
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @since       1.0
+ * @version     $Revision: 4866 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jukka Hassinen <Jukka.Hassinen@BrainAlliance.com>
+ * @author      Nicolas BĂ©rard-Nault <nicobn@php.net>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Builder_Record
+{
+    /**
+     * Path
+     *
+     * the path where imported files are being generated
+     *
+     * @var string $_path
+     */
+    protected $_path = '';
+
+    /**
+     * packagesPrefix
+     *
+     * @var string
+     */
+    protected $_packagesPrefix = 'Package';
+
+    /**
+     * packagesPath
+     *
+     * @var string
+     */
+    protected $_packagesPath = '';
+
+    /**
+     * suffix
+     *
+     * File suffix to use when writing class definitions
+     *
+     * @var string $suffix
+     */
+    protected $_suffix = '.php';
+
+    /**
+     * generateBaseClasses
+     *
+     * Bool true/false for whether or not to generate base classes
+     *
+     * @var string $suffix
+     */
+    protected $_generateBaseClasses = true;
+
+    /**
+     * baseClassesDirectory
+     *
+     * Directory to put the generate base classes in
+     *
+     * @var string $suffix
+     */
+    protected $_baseClassesDirectory = 'generated';
+
+    /**
+     * baseClassName
+     *
+     * @var string
+     */
+    protected $_baseClassName = 'Doctrine_Entity';
+
+    /**
+     * tpl
+     *
+     * Class template used for writing classes
+     *
+     * @var $_tpl
+     */
+    protected static $_tpl;
+
+    /**
+     * __construct
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        $this->loadTemplate();
+    }
+
+    /**
+     * setTargetPath
+     *
+     * @param string path   the path where imported files are being generated
+     * @return
+     */
+    public function setTargetPath($path)
+    {
+        if ( ! $this->_packagesPath) {
+            $this->setPackagesPath($path . DIRECTORY_SEPARATOR . 'packages');
+        }
+
+        $this->_path = $path;
+    }
+
+    /**
+     * setPackagePath
+     *
+     * @param string $packagesPrefix
+     * @return void
+     */
+    public function setPackagesPrefix($packagesPrefix)
+    {
+        $this->_packagesPrefix = $packagesPrefix;
+    }
+
+    /**
+     * setPackagesPath
+     *
+     * @param string $packagesPath
+     * @return void
+     */
+    public function setPackagesPath($packagesPath)
+    {
+        $this->_packagesPath = $packagesPath;
+    }
+
+    /**
+     * generateBaseClasses
+     *
+     * Specify whether or not to generate classes which extend from generated base classes
+     *
+     * @param string $bool
+     * @return void
+     */
+    public function generateBaseClasses($bool = null)
+    {
+        if ($bool !== null) {
+            $this->_generateBaseClasses = $bool;
+        }
+
+        return $this->_generateBaseClasses;
+    }
+
+    /**
+     * setBaseClassesDirectory
+     *
+     * @return void
+     */
+    public function setBaseClassesDirectory($baseClassesDirectory)
+    {
+        $this->_baseClassesDirectory;
+    }
+
+    /**
+     * setBaseClassName
+     *
+     * @package default
+     */
+    public function setBaseClassName($className)
+    {
+        $this->_baseClassName = $className;
+    }
+
+    /**
+     * setSuffix
+     *
+     * @param string $suffix
+     * @return void
+     */
+    public function setSuffix($suffix)
+    {
+        $this->_suffix = $suffix;
+    }
+
+    /**
+     * getTargetPath
+     *
+     * @return string       the path where imported files are being generated
+     */
+    public function getTargetPath()
+    {
+        return $this->_path;
+    }
+
+    /**
+     * setOptions
+     *
+     * @param string $options
+     * @return void
+     */
+    public function setOptions($options)
+    {
+        if (!empty($options)) {
+            foreach ($options as $key => $value) {
+                $this->setOption($key, $value);
+            }
+        }
+    }
+
+    /**
+     * setOption
+     *
+     * @param string $key
+     * @param string $value
+     * @return void
+     */
+    public function setOption($key, $value)
+    {
+        $name = 'set' . Doctrine::classify($key);
+
+        if (method_exists($this, $name)) {
+            $this->$name($value);
+        } else {
+            $key = '_' . $key;
+            $this->$key = $value;
+        }
+    }
+
+    /**
+     * loadTemplate
+     *
+     * Loads the class template used for generating classes
+     *
+     * @return void
+     */
+    public function loadTemplate()
+    {
+        if (isset(self::$_tpl)) {
+            return;
+        }
+
+        self::$_tpl =<<<END
+/**
+ * This class has been auto-generated by the Doctrine ORM Framework
+ */
+%sclass %s extends %s
+{
+%s
+%s
+%s
+}
+END;
+    }
+
+    /*
+     * Build the table definition of a Doctrine_Entity object
+     *
+     * @param  string $table
+     * @param  array  $tableColumns
+     */
+    public function buildTableDefinition(array $definition)
+    {
+        // If the inheritance type if simple or column aggregation then we do not need a table definition
+        if (isset($definition['inheritance']['type']) && ($definition['inheritance']['type'] == 'simple' || $definition['inheritance']['type'] == 'aggregation')) {
+            return;
+        }
+
+        $ret = array();
+
+        $i = 0;
+
+        if (isset($definition['inheritance']['extends']) && ! (isset($definition['override_parent']) && $definition['override_parent'] == true)) {
+            $ret[$i] = "    parent::setTableDefinition();";
+            $i++;
+        }
+
+        if (isset($definition['tableName']) && !empty($definition['tableName'])) {
+            $ret[$i] = "    ".'$this->setTableName(\''. $definition['tableName'].'\');';
+
+            $i++;
+        }
+
+        if (isset($definition['columns']) && is_array($definition['columns']) && !empty($definition['columns'])) {
+            $ret[$i] = $this->buildColumns($definition['columns']);
+            $i++;
+        }
+
+        if (isset($definition['indexes']) && is_array($definition['indexes']) && !empty($definition['indexes'])) {
+            $ret[$i] = $this->buildIndexes($definition['indexes']);
+            $i++;
+        }
+
+        if (isset($definition['attributes']) && is_array($definition['attributes']) && !empty($definition['attributes'])) {
+            $ret[$i] = $this->buildAttributes($definition['attributes']);
+            $i++;
+        }
+
+        if (isset($definition['options']) && is_array($definition['options']) && !empty($definition['options'])) {
+            $ret[$i] = $this->buildOptions($definition['options']);
+            $i++;
+        }
+
+        if (isset($definition['subclasses']) && is_array($definition['subclasses']) && !empty($definition['subclasses'])) {
+            $ret[$i] = '    $this->setSubclasses(' . var_export($definition['subclasses'], true) . ');';
+            $i++;
+        }
+
+        $code = implode("\n", $ret);
+        $code = trim($code);
+
+        if ($code) {
+          return "\n  public function setTableDefinition()"."\n  {\n    ".$code."\n  }";
+        }
+    }
+
+    /**
+     * buildSetUp
+     *
+     * @param  array $options
+     * @param  array $columns
+     * @param  array $relations
+     * @return string
+     */
+    public function buildSetUp(array $definition)
+    {
+        $ret = array();
+        $i = 0;
+
+        if (isset($definition['inheritance']['extends']) && ! (isset($definition['override_parent']) && $definition['override_parent'] == true)) {
+            $ret[$i] = "    parent::setUp();";
+            $i++;
+        }
+
+        if (isset($definition['relations']) && is_array($definition['relations']) && !empty($definition['relations'])) {
+            foreach ($definition['relations'] as $name => $relation) {
+                $class = isset($relation['class']) ? $relation['class']:$name;
+                $alias = (isset($relation['alias']) && $relation['alias'] !== $relation['class']) ? ' as ' . $relation['alias'] : '';
+
+                if ( ! isset($relation['type'])) {
+                    $relation['type'] = Doctrine_Relation::ONE;
+                }
+
+                if ($relation['type'] === Doctrine_Relation::ONE ||
+                    $relation['type'] === Doctrine_Relation::ONE_COMPOSITE) {
+                    $ret[$i] = "    ".'$this->hasOne(\'' . $class . $alias . '\'';
+                } else {
+                    $ret[$i] = "    ".'$this->hasMany(\'' . $class . $alias . '\'';
+                }
+
+                $a = array();
+
+                if (isset($relation['refClass'])) {
+                    $a[] = '\'refClass\' => ' . var_export($relation['refClass'], true);
+                }
+
+                if (isset($relation['deferred']) && $relation['deferred']) {
+                    $a[] = '\'default\' => ' . var_export($relation['deferred'], true);
+                }
+
+                if (isset($relation['local']) && $relation['local']) {
+                    $a[] = '\'local\' => ' . var_export($relation['local'], true);
+                }
+
+                if (isset($relation['foreign']) && $relation['foreign']) {
+                    $a[] = '\'foreign\' => ' . var_export($relation['foreign'], true);
+                }
+
+                if (isset($relation['onDelete']) && $relation['onDelete']) {
+                    $a[] = '\'onDelete\' => ' . var_export($relation['onDelete'], true);
+                }
+
+                if (isset($relation['onUpdate']) && $relation['onUpdate']) {
+                    $a[] = '\'onUpdate\' => ' . var_export($relation['onUpdate'], true);
+                }
+
+                if (isset($relation['equal']) && $relation['equal']) {
+                    $a[] = '\'equal\' => ' . var_export($relation['equal'], true);
+                }
+
+                if ( ! empty($a)) {
+                    $ret[$i] .= ', ' . 'array(';
+                    $length = strlen($ret[$i]);
+                    $ret[$i] .= implode(',' . PHP_EOL . str_repeat(' ', $length), $a) . ')';
+                }
+
+                $ret[$i] .= ');'."\n";
+                $i++;
+            }
+        }
+
+        if (isset($definition['templates']) && is_array($definition['templates']) && !empty($definition['templates'])) {
+            $ret[$i] = $this->buildTemplates($definition['templates']);
+            $i++;
+        }
+
+        if (isset($definition['actAs']) && is_array($definition['actAs']) && !empty($definition['actAs'])) {
+            $ret[$i] = $this->buildActAs($definition['actAs']);
+            $i++;
+        }
+
+        $code = implode("\n", $ret);
+        $code = trim($code);
+
+        if ($code) {
+          return "\n  public function setUp()\n  {\n    ".$code."\n  }";
+        }
+    }
+
+    /**
+     * buildColumns
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildColumns(array $columns)
+    {
+        $build = null;
+        foreach ($columns as $name => $column) {
+            $build .= "    ".'$this->hasColumn(\'' . $name . '\', \'' . $column['type'] . '\'';
+
+            if ($column['length']) {
+                $build .= ', ' . $column['length'];
+            } else {
+                $build .= ', null';
+            }
+
+            $options = $column;
+            $unset = array('name', 'type', 'length', 'ptype');
+            foreach ($options as $key => $value) {
+                if (in_array($key, $unset) || $value === null) {
+                    unset($options[$key]);
+                }
+            }
+
+            if (is_array($options) && !empty($options)) {
+                $build .= ', ' . var_export($options, true);
+            }
+
+            $build .= ");\n";
+        }
+
+        return $build;
+    }
+
+    /*
+     * Build the accessors
+     *
+     * @param  string $table
+     * @param  array  $columns
+     */
+    public function buildAccessors(array $definition)
+    {
+        $accessors = array();
+        foreach (array_keys($definition['columns']) as $name) {
+            $accessors[] = $name;
+        }
+
+        foreach ($definition['relations'] as $relation) {
+            $accessors[] = $relation['alias'];
+        }
+
+        $ret = '';
+        foreach ($accessors as $name) {
+            // getters
+            $ret .= "\n  public function get" . Doctrine_Inflector::classify(Doctrine_Inflector::tableize($name)) . "(\$load = true)\n";
+            $ret .= "  {\n";
+            $ret .= "    return \$this->get('{$name}', \$load);\n";
+            $ret .= "  }\n";
+
+            // setters
+            $ret .= "\n  public function set" . Doctrine_Inflector::classify(Doctrine_Inflector::tableize($name)) . "(\${$name}, \$load = true)\n";
+            $ret .= "  {\n";
+            $ret .= "    return \$this->set('{$name}', \${$name}, \$load);\n";
+            $ret .= "  }\n";
+        }
+
+        return $ret;
+    }
+
+    /**
+     * buildTemplates
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildTemplates(array $templates)
+    {
+        $build = '';
+        foreach ($templates as $name => $options) {
+
+            if (is_array($options) && !empty($options)) {
+                $optionsPhp = var_export($options, true);
+
+                $build .= "    \$this->loadTemplate('" . $name . "', " . $optionsPhp . ");\n";
+            } else {
+                if (isset($templates[0])) {
+                    $build .= "    \$this->loadTemplate('" . $options . "');\n";
+                } else {
+                    $build .= "    \$this->loadTemplate('" . $name . "');\n";
+                }
+            }
+        }
+
+        return $build;
+    }
+
+    /**
+     * buildActAs
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildActAs(array $actAs)
+    {
+        $build = '';
+        foreach ($actAs as $name => $options) {
+            if (is_array($options) && !empty($options)) {
+                $optionsPhp = var_export($options, true);
+
+                $build .= "    \$this->actAs('" . $name . "', " . $optionsPhp . ");\n";
+            } else {
+                if (isset($actAs[0])) {
+                    $build .= "    \$this->actAs('" . $options . "');\n";
+                } else {
+                    $build .= "    \$this->actAs('" . $name . "');\n";
+                }
+            }
+        }
+
+        return $build;
+    }
+
+    /**
+     * buildAttributes
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildAttributes(array $attributes)
+    {
+        $build = "\n";
+        foreach ($attributes as $key => $value) {
+
+            if (is_bool($value))
+            {
+              $values = $value ? 'true':'false';
+            } else {
+                if ( ! is_array($value)) {
+                    $value = array($value);
+                }
+
+                $values = '';
+                foreach ($value as $attr) {
+                    $values .= "Doctrine::" . strtoupper($key) . "_" . strtoupper($attr) . ' ^ ';
+                }
+
+                // Trim last ^
+                $values = substr($values, 0, strlen($values) - 3);
+            }
+
+            $build .= "    \$this->setAttribute(Doctrine::ATTR_" . strtoupper($key) . ", " . $values . ");\n";
+        }
+
+        return $build;
+    }
+
+    /**
+     * buildTableOptions
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildOptions(array $options)
+    {
+        $build = '';
+        foreach ($options as $name => $value) {
+            $build .= "    \$this->option('$name', " . var_export($value, true) . ");\n";
+        }
+
+        return $build;
+    }
+
+    /**
+     * buildIndexes
+     *
+     * @param string $array
+     * @return void
+     */
+    public function buildIndexes(array $indexes)
+    {
+      $build = '';
+
+      foreach ($indexes as $indexName => $definitions) {
+          $build .= "\n    \$this->index('" . $indexName . "'";
+          $build .= ', ' . var_export($definitions, true);
+          $build .= ');';
+      }
+
+      return $build;
+    }
+
+    /**
+     * buildDefinition
+     *
+     * @param array $definition
+     * @return string
+     */
+    public function buildDefinition(array $definition)
+    {
+        if ( ! isset($definition['className'])) {
+            throw new Doctrine_Builder_Exception('Missing class name.');
+        }
+
+        $abstract = isset($definition['abstract']) && $definition['abstract'] === true ? 'abstract ':null;
+        $className = $definition['className'];
+        $extends = isset($definition['inheritance']['extends']) ? $definition['inheritance']['extends']:$this->_baseClassName;
+
+        if ( ! (isset($definition['no_definition']) && $definition['no_definition'] === true)) {
+            $tableDefinitionCode = $this->buildTableDefinition($definition);
+            $setUpCode = $this->buildSetUp($definition);
+        } else {
+            $tableDefinitionCode = null;
+            $setUpCode = null;
+        }
+
+        $accessorsCode = (isset($definition['generate_accessors']) && $definition['generate_accessors'] === true) ? $this->buildAccessors($definition):null;
+
+        $content = sprintf(self::$_tpl, $abstract,
+                                       $className,
+                                       $extends,
+                                       $tableDefinitionCode,
+                                       $setUpCode,
+                                       $accessorsCode);
+
+        return $content;
+    }
+
+    /**
+     * buildRecord
+     *
+     * @param array $options
+     * @param array $columns
+     * @param array $relations
+     * @param array $indexes
+     * @param array $attributes
+     * @param array $templates
+     * @param array $actAs
+     * @return void=
+     */
+    public function buildRecord(array $definition)
+    {
+        if ( ! isset($definition['className'])) {
+            throw new Doctrine_Builder_Exception('Missing class name.');
+        }
+
+        if ($this->generateBaseClasses()) {
+            $definition['is_package'] = (isset($definition['package']) && $definition['package']) ? true:false;
+
+            if ($definition['is_package']) {
+                $e = explode('.', $definition['package']);
+                $definition['package_name'] = $e[0];
+                unset($e[0]);
+
+                $definition['package_path'] = implode(DIRECTORY_SEPARATOR, $e);
+            }
+
+            // Top level definition that extends from all the others
+            $topLevel = $definition;
+            unset($topLevel['tableName']);
+
+            // If we have a package then we need to make this extend the package definition and not the base definition
+            // The package definition will then extends the base definition
+            $topLevel['inheritance']['extends'] = (isset($topLevel['package']) && $topLevel['package']) ? $this->_packagesPrefix . $topLevel['className']:'Base' . $topLevel['className'];
+            $topLevel['no_definition'] = true;
+            $topLevel['generate_once'] = true;
+            $topLevel['is_main_class'] = true;
+            unset($topLevel['connection']);
+
+            // Package level definition that extends from the base definition
+            if (isset($definition['package'])) {
+
+                $packageLevel = $definition;
+                $packageLevel['className'] = $topLevel['inheritance']['extends'];
+                $packageLevel['inheritance']['extends'] = 'Base' . $topLevel['className'];
+                $packageLevel['no_definition'] = true;
+                $packageLevel['abstract'] = true;
+                $packageLevel['override_parent'] = true;
+                $packageLevel['generate_once'] = true;
+                $packageLevel['is_package_class'] = true;
+                unset($packageLevel['connection']);
+            }
+
+            $baseClass = $definition;
+            $baseClass['className'] = 'Base' . $baseClass['className'];
+            $baseClass['abstract'] = true;
+            $baseClass['override_parent'] = false;
+            $baseClass['is_base_class'] = true;
+
+            $this->writeDefinition($baseClass);
+
+            if (!empty($packageLevel)) {
+                $this->writeDefinition($packageLevel);
+            }
+
+            $this->writeDefinition($topLevel);
+        } else {
+            $this->writeDefinition($definition);
+        }
+    }
+
+    /**
+     * writeDefinition
+     *
+     * @param array $options
+     * @param array $columns
+     * @param array $relations
+     * @param array $indexes
+     * @param array $attributes
+     * @param array $templates
+     * @param array $actAs
+     * @return void
+     */
+    public function writeDefinition(array $definition)
+    {
+        $definitionCode = $this->buildDefinition($definition);
+
+        $fileName = $definition['className'] . $this->_suffix;
+
+        $packagesPath = $this->_packagesPath ? $this->_packagesPath:$this->_path;
+
+        // If this is a main class that either extends from Base or Package class
+        if (isset($definition['is_main_class']) && $definition['is_main_class']) {
+            // If is package then we need to put it in a package subfolder
+            if (isset($definition['is_package']) && $definition['is_package']) {
+                $writePath = $this->_path . DIRECTORY_SEPARATOR . $definition['package_name'];
+            // Otherwise lets just put it in the root of the path
+            } else {
+                $writePath = $this->_path;
+            }
+        }
+
+        // If is the package class then we need to make the path to the complete package
+        if (isset($definition['is_package_class']) && $definition['is_package_class']) {
+            $path = str_replace('.', DIRECTORY_SEPARATOR, trim($definition['package']));
+
+            $writePath = $packagesPath . DIRECTORY_SEPARATOR . $path;
+        }
+
+        // If it is the base class of the doctrine record definition
+        if (isset($definition['is_base_class']) && $definition['is_base_class']) {
+            // If it is a part of a package then we need to put it in a package subfolder
+            if (isset($definition['is_package']) && $definition['is_package']) {
+                $writePath  = $this->_path . DIRECTORY_SEPARATOR . $definition['package_name'] . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory;
+            // Otherwise lets just put it in the root generated folder
+            } else {
+                $writePath = $this->_path . DIRECTORY_SEPARATOR . $this->_baseClassesDirectory;
+            }
+        }
+
+        if (isset($writePath)) {
+            Doctrine_Lib::makeDirectories($writePath);
+
+            $writePath .= DIRECTORY_SEPARATOR . $fileName;
+        } else {
+            Doctrine_Lib::makeDirectories($this->_path);
+
+            $writePath = $this->_path . DIRECTORY_SEPARATOR . $fileName;
+        }
+
+        $code = "<?php" . PHP_EOL;
+
+        if (isset($definition['connection']) && $definition['connection']) {
+            $code .= "// Connection Component Binding\n";
+            $code .= "Doctrine_Manager::getInstance()->bindComponent('" . $definition['connectionClassName'] . "', '" . $definition['connection'] . "');\n";
+        }
+
+        $code .= PHP_EOL . $definitionCode;
+
+        if (isset($definition['generate_once']) && $definition['generate_once'] === true) {
+            if (!file_exists($writePath)) {
+                $bytes = file_put_contents($writePath, $code);
+            }
+        } else {
+            $bytes = file_put_contents($writePath, $code);
+        }
+
+        if (isset($bytes) && $bytes === false) {
+            throw new Doctrine_Builder_Exception("Couldn't write file " . $writePath);
+        }
+    }
+}
diff --git a/lib/Doctrine/TODO/Cli/AnsiColorFormatter.php b/lib/Doctrine/TODO/Cli/AnsiColorFormatter.php
new file mode 100644
index 000000000..4ba2eaebc
--- /dev/null
+++ b/lib/Doctrine/TODO/Cli/AnsiColorFormatter.php
@@ -0,0 +1,155 @@
+<?php
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ *  $Id: AnsiColorFormatter.php 2702 2007-10-03 21:43:22Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_AnsiColorFormatter provides methods to colorize text to be displayed on a console.
+ *
+ * @package    Doctrine
+ * @subpackage Cli
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: sfAnsiColorFormatter.class.php 5250 2007-09-24 08:11:50Z fabien $
+ */
+class Doctrine_Cli_AnsiColorFormatter extends Doctrine_Cli_Formatter
+{
+    protected
+        $_styles = array(
+            'HEADER'  => array('fg' => 'black', 'bold' => true),
+            'ERROR'   => array('bg' => 'red', 'fg' => 'white', 'bold' => true),
+            'INFO'    => array('fg' => 'green', 'bold' => true),
+            'COMMENT' => array('fg' => 'yellow'),
+            ),
+        $_options    = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8),
+        $_foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37),
+        $_background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47);
+
+    /**
+     * Sets a new style.
+     *
+     * @param string The style name
+     * @param array  An array of options
+     */
+    public function setStyle($name, $options = array())
+    {
+        $this->_styles[$name] = $options;
+    }
+
+    /**
+     * Formats a text according to the given style or parameters.
+     *
+     * @param  string The test to style
+     * @param  mixed  An array of options or a style name
+     *
+     * @return string The styled text
+     */
+    public function format($text = '', $parameters = array(), $stream = STDOUT)
+    {
+        if ( ! $this->supportsColors($stream)) {
+            return $text;
+        }
+
+        if ( ! is_array($parameters) && 'NONE' == $parameters) {
+            return $text;
+        }
+
+        if ( ! is_array($parameters) && isset($this->_styles[$parameters])) {
+            $parameters = $this->_styles[$parameters];
+        }
+
+        $codes = array();
+        if (isset($parameters['fg'])) {
+            $codes[] = $this->_foreground[$parameters['fg']];
+        }
+        
+        if (isset($parameters['bg'])) {
+            $codes[] = $this->_background[$parameters['bg']];
+        }
+        
+        foreach ($this->_options as $option => $value) {
+            if (isset($parameters[$option]) && $parameters[$option]) {
+                $codes[] = $value;
+            }
+        }
+
+        return "\033[".implode(';', $codes).'m'.$text."\033[0m";
+    }
+
+    /**
+     * Formats a message within a section.
+     *
+     * @param string  The section name
+     * @param string  The text message
+     * @param integer The maximum size allowed for a line (65 by default)
+     */
+    public function formatSection($section, $text, $size = null)
+    {
+        $width = 9 + strlen($this->format('', 'INFO'));
+
+        return sprintf(">> %-${width}s %s", $this->format($section, 'INFO'), $this->excerpt($text, $size));
+    }
+
+    /**
+     * Truncates a line.
+     *
+     * @param string  The text
+     * @param integer The maximum size of the returned string (65 by default)
+     *
+     * @return string The truncated string
+     */
+    public function excerpt($text, $size = null)
+    {
+        if ( ! $size) {
+            $size = $this->size;
+        }
+
+        if (strlen($text) < $size) {
+            return $text;
+        }
+
+        $subsize = floor(($size - 3) / 2);
+
+        return substr($text, 0, $subsize).$this->format('...', 'INFO').substr($text, -$subsize);
+    }
+
+    /**
+     * Returns true if the stream supports colorization.
+     *
+     * Colorization is disabled if not supported by the stream:
+     *
+     *  -  windows
+     *  -  non tty consoles
+     *
+     * @param  mixed A stream
+     *
+     * @return Boolean true if the stream supports colorization, false otherwise
+     */
+    public function supportsColors($stream)
+    {
+        return DIRECTORY_SEPARATOR != '\\' && function_exists('posix_isatty') && @posix_isatty($stream);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Cli/Exception.php b/lib/Doctrine/TODO/Cli/Exception.php
new file mode 100644
index 000000000..108275abb
--- /dev/null
+++ b/lib/Doctrine/TODO/Cli/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Cli_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Cli
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Cli_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Cli/Formatter.php b/lib/Doctrine/TODO/Cli/Formatter.php
new file mode 100644
index 000000000..469c53d47
--- /dev/null
+++ b/lib/Doctrine/TODO/Cli/Formatter.php
@@ -0,0 +1,111 @@
+<?php
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/*
+ *  $Id: Formatter.php 2702 2007-10-03 21:43:22Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Cli_Formatter provides methods to format text to be displayed on a console.
+ *
+ * @package    Doctrine
+ * @subpackage Cli
+ * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version    SVN: $Id: Doctrine_Cli_Formatter.class.php 5250 2007-09-24 08:11:50Z fabien $
+ */
+class Doctrine_Cli_Formatter
+{
+    protected $_size = 65;
+
+    /**
+     * __construct
+     *
+     * @param string $maxLineSize 
+     * @return void
+     */
+    function __construct($maxLineSize = 65)
+    {
+        $this->_size = $maxLineSize;
+    }
+
+    /**
+     * Formats a text according to the given parameters.
+     *
+     * @param  string The test to style
+     * @param  mixed  An array of parameters
+     * @param  stream A stream (default to STDOUT)
+     *
+     * @return string The formatted text
+     */
+    public function format($text = '', $parameters = array(), $stream = STDOUT)
+    {
+        return $text;
+    }
+
+    /**
+     * Formats a message within a section.
+     *
+     * @param string  The section name
+     * @param string  The text message
+     * @param integer The maximum size allowed for a line (65 by default)
+     */
+    public function formatSection($section, $text, $size = null)
+    {
+        return sprintf(">> %-$9s %s", $section, $this->excerpt($text, $size));
+    }
+
+    /**
+     * Truncates a line.
+     *
+     * @param string  The text
+     * @param integer The maximum size of the returned string (65 by default)
+     *
+     * @return string The truncated string
+     */
+    public function excerpt($text, $size = null)
+    {
+        if ( ! $size) {
+            $size = $this->_size;
+        }
+
+        if (strlen($text) < $size) {
+            return $text;
+        }
+
+        $subsize = floor(($size - 3) / 2);
+
+        return substr($text, 0, $subsize).'...'.substr($text, -$subsize);
+    }
+
+    /**
+     * Sets the maximum line size.
+     *
+     * @param integer The maximum line size for a message
+     */
+    public function setMaxLineSize($size)
+    {
+        $this->_size = $size;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Data/Exception.php b/lib/Doctrine/TODO/Data/Exception.php
new file mode 100644
index 000000000..05a4b8c1f
--- /dev/null
+++ b/lib/Doctrine/TODO/Data/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 2552 2007-09-19 19:33:00Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Data_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Data
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2552 $
+ */
+class Doctrine_Data_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Data/Export.php b/lib/Doctrine/TODO/Data/Export.php
new file mode 100644
index 000000000..5d86ce1b4
--- /dev/null
+++ b/lib/Doctrine/TODO/Data/Export.php
@@ -0,0 +1,183 @@
+<?php
+/*
+ *  $Id: Export.php 2552 2007-09-19 19:33:00Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Data_Export
+ *
+ * @package     Doctrine
+ * @subpackage  Data
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2552 $
+ */
+class Doctrine_Data_Export extends Doctrine_Data
+{
+    /**
+     * constructor
+     *
+     * @param string $directory 
+     * @return void
+     */
+    public function __construct($directory)
+    {
+        $this->setDirectory($directory);
+    }
+
+    /**
+     * doExport
+     *
+     * @return void
+     */
+    public function doExport()
+    {
+        $models = Doctrine::getLoadedModels();
+        $specifiedModels = $this->getModels();
+        
+        $data = array();
+        
+        $outputAll = true;
+        
+		    // for situation when the $models array is empty, but the $specifiedModels array isn't
+        if (empty($models)) {
+          $models = $specifiedModels;
+        }
+        
+        foreach ($models AS $name) {
+            
+            if ( ! empty($specifiedModels) AND !in_array($name, $specifiedModels)) {
+                continue;
+            }
+            
+            $class = new $name();
+            $table = $class->getTable();
+            $result = $table->findAll();
+            
+            if ( ! empty($result)) {
+                $data[$name] = $result;
+            }
+        }
+        
+        $data = $this->prepareData($data);
+        
+        return $this->dumpData($data);
+    }
+
+    /**
+     * dumpData
+     *
+     * Dump the prepared data to the fixtures files
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function dumpData(array $data)
+    {
+        $directory = $this->getDirectory();
+        $format = $this->getFormat();
+        
+        if ($this->exportIndividualFiles()) {
+            
+            if (is_array($directory)) {
+                throw new Doctrine_Data_Exception('You must specify a single path to a folder in order to export individual files.');
+            } else if ( ! is_dir($directory) && is_file($directory)) {
+                $directory = dirname($directory);
+            }
+            
+            foreach ($data as $className => $classData) {
+                if ( ! empty($classData)) {
+                    Doctrine_Parser::dump(array($className => $classData), $format, $directory.DIRECTORY_SEPARATOR.$className.'.'.$format);
+                }
+            }
+        } else {
+            if (is_dir($directory)) {
+                $directory .= DIRECTORY_SEPARATOR . 'data.' . $format;
+            }
+            
+            if ( ! empty($data)) {
+                return Doctrine_Parser::dump($data, $format, $directory);
+            }
+        }
+    }
+
+    /**
+     * prepareData
+     *
+     * Prepare the raw data to be exported with the parser
+     *
+     * @param string $data 
+     * @return array
+     */
+    public function prepareData($data)
+    {
+        $preparedData = array();
+        
+        foreach ($data AS $className => $classData) {
+            
+            foreach ($classData as $record) {
+                $className = get_class($record);
+                $recordKey = $className . '_' . implode('_', $record->identifier());
+                
+                $recordData = $record->toArray();
+                
+                foreach ($recordData as $key => $value) {
+                    if ( ! $value) {
+                        continue;
+                    }
+                    
+                    // skip single primary keys, we need to maintain composite primary keys
+                    $keys = (array)$record->getTable()->getIdentifier();
+                    
+                    if (count($keys) <= 1 && in_array($key, $keys)) {
+                        continue;
+                    }
+                    
+                    if ($relation = $this->isRelation($record, $key)) {
+                        $relationAlias = $relation['alias'];
+                        $relationRecord = $record->$relationAlias;
+                        
+                        // If collection then get first so we have an instance of the related record
+                        if ($relationRecord instanceof Doctrine_Collection) {
+                            $relationRecord = $relationRecord->getFirst();
+                        }
+                        
+                        // If relation is null or does not exist then continue
+                        if ($relationRecord instanceof Doctrine_Null || !$relationRecord) {
+                            continue;
+                        }
+                        
+                        // Get class name for relation
+                        $relationClassName = get_class($relationRecord);
+                        
+                        $relationValue = $relationClassName . '_' . $value;
+                        
+                        $preparedData[$className][$recordKey][$relationAlias] = $relationValue;
+                    } else {                        
+                        $preparedData[$className][$recordKey][$key] = $value;
+                    }
+                }
+            }
+        }
+        
+        return $preparedData;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Data/Import.php b/lib/Doctrine/TODO/Data/Import.php
new file mode 100644
index 000000000..482e29701
--- /dev/null
+++ b/lib/Doctrine/TODO/Data/Import.php
@@ -0,0 +1,380 @@
+<?php
+/*
+ *  $Id: Import.php 2552 2007-09-19 19:33:00Z Jonathan.Wage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Data_Import
+ *
+ * @package     Doctrine
+ * @package     Data
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2552 $
+ */
+class Doctrine_Data_Import extends Doctrine_Data
+{
+    protected $_importedObjects = array();
+    protected $_rows = array();
+    
+    /**
+     * constructor
+     *
+     * @param string $directory 
+     * @return void
+     */
+    public function __construct($directory = null)
+    {
+        if ($directory !== null) {
+            $this->setDirectory($directory);
+        }
+    }
+
+    /**
+     * doImport
+     *
+     * @return void
+     */
+    public function doImport()
+    {
+        $directory = $this->getDirectory();
+        
+        $array = array();
+        
+        if ($directory !== null) {
+            foreach ((array) $directory as $dir) {
+                $e = explode('.', $dir);
+                
+                // If they specified a specific yml file
+                if (end($e) == 'yml') {
+                    $array = array_merge($array, Doctrine_Parser::load($dir, $this->getFormat()));
+                // If they specified a directory
+                } else if(is_dir($dir)) {
+                    $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
+                                                            RecursiveIteratorIterator::LEAVES_ONLY);
+
+                    foreach ($it as $file) {
+                        $e = explode('.', $file->getFileName());
+                        if (in_array(end($e), $this->getFormats())) {
+                            $array = array_merge($array, Doctrine_Parser::load($file->getPathName(), $this->getFormat()));
+                        }
+                    }   
+                }
+            }
+        }
+        
+        $this->_loadData($array);
+    }
+    
+    protected function _buildRows($className, $data)
+    {
+        foreach ($data as $rowKey => $row) {
+            // do the same for the row information
+            $this->_rows[$className][$rowKey] = $row;
+            
+            foreach ($row as $key => $value) {
+                if (Doctrine::getTable($className)->hasRelation($key) && is_array($value)) {
+                    $keys = array_keys($value);
+                    
+                    // Skip associative arrays defining keys to relationships
+                    if (!isset($keys[0])) {
+                        $this->_buildRows(Doctrine::getTable($className)->getRelation($key)->getTable()->getOption('name'), $value);
+                    }
+                }
+            }
+        }
+    }
+    
+    protected function _buildNestedSetRows($className, $data)
+    {
+        foreach ($data as $rowKey => $row) {
+            $children = isset($row['children']) ? $row['children']:array();
+            unset($row['children']);
+            $this->_rows[$className][$rowKey] = $row;
+            
+            $this->_buildNestedSetRows($className, $children);
+        }
+    }
+    
+    protected function _getImportedObject($rowKey)
+    {
+        if (isset($this->_importedObjects[$rowKey])) {
+            return $this->_importedObjects[$rowKey];
+        } else {
+            throw new Doctrine_Data_Exception('Invalid row key specified: ' . $rowKey);
+        }
+    }
+    
+    protected function _processRow($rowKey, $row)
+    {
+        $obj = $this->_importedObjects[$rowKey];
+        
+        foreach ($row as $key => $value) {
+            if ($obj->getTable()->hasField($key)) {
+                $obj->set($key, $value);
+            } else if (method_exists($obj, 'set' . Doctrine::classify($key))) {
+                $func = 'set' . Doctrine::classify($key);
+                $obj->$func($value);
+            } else if ($obj->getTable()->hasRelation($key)) {
+                if (is_array($value)) {
+                    if (isset($value[0])) {
+                        foreach ($value as $link) {
+                            
+                            if ($obj->getTable()->getRelation($key)->getType() === Doctrine_Relation::ONE) {
+                                $obj->set($key, $this->_getImportedObject($link));
+                            } else if ($obj->getTable()->getRelation($key)->getType() === Doctrine_Relation::MANY) {
+                                $relation = $obj->$key;
+                                
+                                $relation[] = $this->_getImportedObject($link);
+                            }
+                        }
+                    } else {
+                        $obj->$key->fromArray($value);
+                    }
+                } else {
+                    $obj->set($key, $this->_getImportedObject($value));
+                }
+            }
+        }
+    }
+    
+    /**
+     * loadData
+     *
+     * @param string $array 
+     * @return void
+     */
+    protected function _loadData(array $array)
+    {
+        $nestedSets = array();
+        
+        $specifiedModels = $this->getModels();
+        $rows = array();
+        
+        foreach ($array as $className => $data) {
+            
+            if ( ! empty($specifiedModels) && !in_array($className, $specifiedModels)) {
+                continue;
+            }
+            
+            // This is simple here to get the templates present for this model
+            // better way?
+            $obj = new $className(null, true);
+            $templates = array_keys($obj->getTable()->getBehaviors());
+            
+            if (in_array('Doctrine_Template_NestedSet', $templates)) {
+                $nestedSets[$className][] = $data;
+                $this->_buildNestedSetRows($className, $data);
+            } else {
+                $this->_buildRows($className, $data);
+            }
+        }
+        
+        $buildRows = array();
+        foreach ($this->_rows as $className => $classRows) {
+            foreach ($classRows as $rowKey => $row) {
+                $buildRows[$rowKey] = $row;
+                $this->_importedObjects[$rowKey] = new $className();
+            }
+        }
+
+        foreach($buildRows as $rowKey => $row) {
+            $this->_processRow($rowKey, $row);
+        }
+
+        $objects = array();
+        foreach ($this->_importedObjects as $object) {
+            $className = get_class($object);
+            $objects[$className] = $className;
+        }
+
+        $manager = Doctrine_Manager::getInstance();
+        foreach ($manager as $connection) {            
+            $tree = $connection->unitOfWork->buildFlushTree($objects);
+            
+            foreach ($tree as $model) {
+                foreach ($this->_importedObjects as $obj) {
+                    $templates = array_keys($obj->getTable()->getTemplates());
+                    
+                    if ($obj instanceof $model && !in_array('Doctrine_Template_NestedSet', $templates)) {
+                        $obj->save();
+                    }
+                }
+            }
+        }
+        
+        foreach ($nestedSets as $className => $sets) {
+            foreach ($sets as $data) {
+                $this->_loadNestedSetData($className, $data);
+            }
+        }
+    }
+    
+    protected function _loadNestedSetData($model, $nestedSetData, $parent = null)
+    {
+        $manager = Doctrine_Manager::getInstance();
+
+        foreach($nestedSetData AS $rowKey => $nestedSet)
+        {
+            $children = array();
+            $data  = array();
+            
+            if( array_key_exists('children', $nestedSet) )
+            {
+                $children = $nestedSet['children'];
+                $children = array_reverse($children, true);
+                unset($nestedSet['children']);
+            }
+
+            $record = $this->_importedObjects[$rowKey];
+            
+            if( !$parent )
+            {
+                $manager->getTable($model)->getTree()->createRoot($record);
+            } else {
+                $parent->getNode()->addChild($record);
+            }
+
+            if( is_array($children) AND !empty($children) )
+            {
+                $this->_loadNestedSetData($model, $children, $record);
+            }
+        }
+    }
+
+    /**
+     * doImportDummyData
+     *
+     * @param string $num 
+     * @return void
+     */
+    public function doImportDummyData($num = 3)
+    {
+        $models = Doctrine::getLoadedModels();
+        
+        $specifiedModels = $this->getModels();
+        
+        foreach ($models as $name) {
+            if ( ! empty($specifiedModels) && !in_array($name, $specifiedModels)) {
+                continue;
+            }
+            
+            for ($i = 0; $i < $num; $i++) {
+                $obj = new $name();
+                
+                $this->populateDummyRecord($obj);
+                
+                $obj->save();
+                
+                $ids[get_class($obj)][] = $obj->identifier();
+            }
+        }
+    }
+    
+    public function populateDummyRecord(Doctrine_Entity $record)
+    {
+        $lorem = explode(' ', "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem 
+                               Ipsum has been the industry's standard dummy text ever since the 1500s, when an 
+                               unknown printer took a galley of type and scrambled it to make a type specimen book. 
+                               It has survived not only five centuries, but also the leap into electronic 
+                               typesetting, remaining essentially unchanged. It was popularised in the 1960s with 
+                               the release of Letraset sheets containing Lorem Ipsum passages, and more recently 
+                               with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.");
+        
+        $columns = array_keys($record->toArray());
+        $pks = (array)$record->getTable()->getIdentifier();
+        
+        foreach ($columns as $column) {
+            
+            if ( ! in_array($column, $pks)) {
+                if ($relation = $this->isRelation($record, $column)) {
+                    $alias = $relation['alias'];
+                    $relationObj = $record->$alias;
+                    
+                    $this->populateDummyRecord($relationObj);
+                    
+                } else {
+                    
+                    $definition = $record->getTable()->getDefinitionOf($column);
+                    
+                    switch($definition['type'])
+                    {
+                        case 'string';     
+                            shuffle($lorem);
+                    
+                            $record->$column = substr(implode(' ', $lorem), 0, $definition['length']);
+                        break;
+                        
+                        case 'integer':
+                            $record->$column = rand();
+                        break;
+                        
+                        case 'boolean':
+                            $record->$column = true;
+                        break;
+                        
+                        case 'float':
+                            $record->$column = number_format(rand($definition['length'], $definition['length']), 2, '.', null);
+                        break;
+                        
+                        case 'array':
+                            $record->$column = array('test' => 'test');
+                        break;
+                        
+                        case 'object':
+                            $record->$column = new stdObject();
+                        break;
+                        
+                        case 'blob':
+                            $record->$column = '';
+                        break;
+                        
+                        case 'clob':
+                            $record->$column = '';
+                        break;
+                        
+                        case 'timestamp':
+                            $record->$column = date('Y-m-d h:i:s', time());
+                        break;
+                        
+                        case 'time':
+                            $record->$column = date('h:i:s', time());
+                        break;
+                        
+                        case 'date':
+                            $record->$column = date('Y-m-d', time());
+                        break;
+                        
+                        case 'enum':
+                            $record->$column = 'test';
+                        break;
+                        
+                        case 'gzip':
+                            $record->$column = 'test';
+                        break;
+                    }
+                }
+            }
+        }
+        
+        return $record;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/File/Index.php b/lib/Doctrine/TODO/File/Index.php
new file mode 100644
index 000000000..a0b302d3e
--- /dev/null
+++ b/lib/Doctrine/TODO/File/Index.php
@@ -0,0 +1,56 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_File_Index
+ *
+ * @package     Doctrine
+ * @subpackage  File
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_File_Index extends Doctrine_Entity
+{
+    public function setTableDefinition()
+    {
+        $this->hasColumn('keyword', 'string', 255, array('notnull' => true,
+                                                         'primary' => true));
+                                                         
+        $this->hasColumn('field', 'string', 50, array('notnull' => true,
+                                                      'primary' => true));
+
+        $this->hasColumn('position', 'string', 255, array('notnull' => true,
+                                                          'primary' => true));
+                                                          
+        $this->hasColumn('file_id', 'integer', 8, array('notnull' => true,
+                                                        'primary' => true));
+    }
+    public function setUp()
+    {
+        $this->hasOne('Doctrine_File', array('local' => 'file_id',
+                                             'foreign' => 'id',
+                                             'onDelete' => 'CASCADE',
+                                             'onUpdate' => 'CASCADE'));
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/FileFinder/GlobToRegex.php b/lib/Doctrine/TODO/FileFinder/GlobToRegex.php
new file mode 100644
index 000000000..8ec65312f
--- /dev/null
+++ b/lib/Doctrine/TODO/FileFinder/GlobToRegex.php
@@ -0,0 +1,127 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_FileFinder_GlobToRegex
+ *
+ * Match globbing patterns against text.
+ *
+ *   if match_glob("foo.*", "foo.bar") echo "matched\n";
+ *
+ * // prints foo.bar and foo.baz
+ * $regex = globToRegex("foo.*");
+ * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t)
+ * {
+ *   if (/$regex/) echo "matched: $car\n";
+ * }
+ *
+ * Doctrine_FileFinder_GlobToRegex implements glob(3) style matching that can be used to match
+ * against text, rather than fetching names from a filesystem.
+ *
+ * based on perl Text::Glob module.
+ *
+ * @package    Doctrine
+ * @subpackage FileFinder
+ * @author     Fabien Potencier <fabien.potencier@gmail.com> php port
+ * @author     Richard Clamp <richardc@unixbeard.net> perl version
+ * @copyright  2004-2005 Fabien Potencier <fabien.potencier@gmail.com>
+ * @copyright  2002 Richard Clamp <richardc@unixbeard.net>
+ * @version    SVN: $Id: Doctrine_FileFinder.class.php 5110 2007-09-15 12:07:18Z fabien $
+ */
+class Doctrine_FileFinder_GlobToRegex
+{
+  protected static $strictLeadingDot = true;
+  protected static $strictWildcardSlash = true;
+
+  public static function setStrictLeadingDot($boolean)
+  {
+    self::$strictLeadingDot = $boolean;
+  }
+
+  public static function setStrictWildcardSlash($boolean)
+  {
+    self::$strictWildcardSlash = $boolean;
+  }
+
+  /**
+   * Returns a compiled regex which is the equiavlent of the globbing pattern.
+   *
+   * @param  string glob pattern
+   * @return string regex
+   */
+  public static function globToRegex($glob)
+  {
+    $firstByte = true;
+    $escaping = false;
+    $inCurlies = 0;
+    $regex = '';
+    for ($i = 0; $i < strlen($glob); $i++) {
+      $car = $glob[$i];
+      if ($firstByte) {
+        if (self::$strictLeadingDot && $car != '.') {
+          $regex .= '(?=[^\.])';
+        }
+
+        $firstByte = false;
+      }
+
+      if ($car == '/') {
+        $firstByte = true;
+      }
+
+      if ($car == '.' || $car == '(' || $car == ')' || $car == '|' || $car == '+' || $car == '^' || $car == '$') {
+        $regex .= "\\$car";
+      } else if ($car == '*') {
+        $regex .= ($escaping ? "\\*" : (self::$strictWildcardSlash ? "[^/]*" : ".*"));
+      } else if ($car == '?') {
+        $regex .= ($escaping ? "\\?" : (self::$strictWildcardSlash ? "[^/]" : "."));
+      } else if ($car == '{') {
+        $regex .= ($escaping ? "\\{" : "(");
+        if ( ! $escaping) {
+            ++$inCurlies;
+        }
+      } else if ($car == '}' && $inCurlies) {
+        $regex .= ($escaping ? "}" : ")");
+        if ( ! $escaping) {
+            --$inCurlies;
+        }
+      } else if ($car == ',' && $inCurlies) {
+        $regex .= ($escaping ? "," : "|");
+      } else if ($car == "\\") {
+        if ($escaping) {
+          $regex .= "\\\\";
+          $escaping = false;
+        } else {
+          $escaping = true;
+        }
+
+        continue;
+      } else {
+        $regex .= $car;
+        $escaping = false;
+      }
+
+      $escaping = false;
+    }
+
+    return "#^$regex$#";
+  }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/FileFinder/NumberCompare.php b/lib/Doctrine/TODO/FileFinder/NumberCompare.php
new file mode 100644
index 000000000..ab435dc76
--- /dev/null
+++ b/lib/Doctrine/TODO/FileFinder/NumberCompare.php
@@ -0,0 +1,106 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_FileFinder_NumberCompare
+ *
+ * Numeric comparisons.
+ *
+ * Doctrine_FileFinder_NumberCompare compiles a simple comparison to an anonymous
+ * subroutine, which you can call with a value to be tested again.
+ *
+ * Now this would be very pointless, if Doctrine_FileFinder_NumberCompare didn't understand
+ * magnitudes.
+ *
+ * The target value may use magnitudes of kilobytes (k, ki),
+ * megabytes (m, mi), or gigabytes (g, gi).  Those suffixed
+ * with an i use the appropriate 2**n version in accordance with the
+ * IEC standard: http://physics.nist.gov/cuu/Units/binary.html
+ *
+ * based on perl Number::Compare module.
+ *
+ * @package    Doctrine
+ * @subpackage FileFinder
+ * @author     Fabien Potencier <fabien.potencier@gmail.com> php port
+ * @author     Richard Clamp <richardc@unixbeard.net> perl version
+ * @copyright  2004-2005 Fabien Potencier <fabien.potencier@gmail.com>
+ * @copyright  2002 Richard Clamp <richardc@unixbeard.net>
+ * @see        http://physics.nist.gov/cuu/Units/binary.html
+ * @version    SVN: $Id: Doctrine_FileFinder.class.php 5110 2007-09-15 12:07:18Z fabien $
+ */
+class Doctrine_FileFinder_NumberCompare
+{
+  protected $test = '';
+
+  public function __construct($test)
+  {
+    $this->test = $test;
+  }
+
+  public function test($number)
+  {
+    if ( ! preg_match('{^([<>]=?)?(.*?)([kmg]i?)?$}i', $this->test, $matches)) {
+      throw new Doctrine_Exception(sprintf('don\'t understand "%s" as a test.', $this->test));
+    }
+
+    $target = array_key_exists(2, $matches) ? $matches[2] : '';
+    $magnitude = array_key_exists(3, $matches) ? $matches[3] : '';
+    if (strtolower($magnitude) == 'k') {
+        $target *=           1000;
+    }
+    
+    if (strtolower($magnitude) == 'ki') {
+        $target *=           1024;
+    }
+    
+    if (strtolower($magnitude) == 'm') {
+        $target *=        1000000;
+    }
+    
+    if (strtolower($magnitude) == 'mi') {
+        $target *=      1024*1024;
+    }
+    
+    if (strtolower($magnitude) == 'g') {
+        $target *=     1000000000;
+    }
+    
+    if (strtolower($magnitude) == 'gi') {
+        $target *= 1024*1024*1024;
+    }
+    
+    $comparison = array_key_exists(1, $matches) ? $matches[1] : '==';
+
+    if ($comparison == '==' || $comparison == '') {
+      return ($number == $target);
+    } else if ($comparison == '>') {
+      return ($number > $target);
+    } else if ($comparison == '>=') {
+      return ($number >= $target);
+    } else if ($comparison == '<') {
+      return ($number < $target);
+    } else if ($comparison == '<=') {
+      return ($number <= $target);
+    }
+
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/I18n/Exception.php b/lib/Doctrine/TODO/I18n/Exception.php
new file mode 100644
index 000000000..cb5abd460
--- /dev/null
+++ b/lib/Doctrine/TODO/I18n/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+ 
+/**
+ * Doctrine_I18n_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  I18n
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_I18n_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Exception.php b/lib/Doctrine/TODO/Log/Exception.php
new file mode 100755
index 000000000..bb62d9099
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 3155 2007-11-14 13:13:23Z ppetermann $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @category    Doctrine
+ * @package     Log
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Exception extends Doctrine_Exception
+{
+
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Filter/Interface.php b/lib/Doctrine/TODO/Log/Filter/Interface.php
new file mode 100644
index 000000000..43a1bd6d9
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Filter/Interface.php
@@ -0,0 +1,41 @@
+<?php
+/*
+ *  $Id: Interface.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+interface Doctrine_Log_Filter_Interface
+{
+    /**
+     * Returns TRUE to accept the message, FALSE to block it.
+     *
+     * @param  array    $event    event data
+     * @return boolean            accepted?
+     */
+    public function accept($event);
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Filter/Message.php b/lib/Doctrine/TODO/Log/Filter/Message.php
new file mode 100644
index 000000000..4a9f97aac
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Filter/Message.php
@@ -0,0 +1,64 @@
+<?php
+/*
+ *  $Id: Message.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Filter_Message implements Doctrine_Log_Filter_Interface
+{
+    /**
+     * @var string
+     */
+    protected $_regexp;
+
+    /**
+     * Filter out any log messages not matching $regexp.
+     *
+     * @param  string  $regexp     Regular expression to test the log message
+     * @throws Doctrine_Log_Exception
+     */
+    public function __construct($regexp)
+    {
+        if (@preg_match($regexp, '') === false) {
+            throw new Doctrine_Log_Exception("Invalid regular expression '$regexp'");
+        }
+        $this->_regexp = $regexp;
+    }
+
+    /**
+     * Returns TRUE to accept the message, FALSE to block it.
+     *
+     * @param  array    $event    event data
+     * @return boolean            accepted?
+     */
+    public function accept($event)
+    {
+        return preg_match($this->_regexp, $event['message']) > 0;
+    }
+
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Filter/Priority.php b/lib/Doctrine/TODO/Log/Filter/Priority.php
new file mode 100644
index 000000000..e51d75a04
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Filter/Priority.php
@@ -0,0 +1,72 @@
+<?php
+/*
+ *  $Id: Priority.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Filter_Priority implements Doctrine_Log_Filter_Interface
+{
+    /**
+     * @var integer
+     */
+    protected $_priority;
+
+    /**
+     * @var string
+     */
+    protected $_operator;
+
+    /**
+     * Filter logging by $priority.  By default, it will accept any log
+     * event whose priority value is less than or equal to $priority.
+     *
+     * @param  integer  $priority  Priority
+     * @param  string   $operator  Comparison operator
+     * @throws Doctrine_Log_Exception
+     */
+    public function __construct($priority, $operator = '<=')
+    {
+        if (! is_integer($priority)) {
+            throw new Doctrine_Log_Exception('Priority must be an integer');
+        }
+
+        $this->_priority = $priority;
+        $this->_operator = $operator;
+    }
+
+    /**
+     * Returns TRUE to accept the message, FALSE to block it.
+     *
+     * @param  array    $event    event data
+     * @return boolean            accepted?
+     */
+    public function accept($event)
+    {
+        return version_compare($event['priority'], $this->_priority, $this->_operator);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Filter/Suppress.php b/lib/Doctrine/TODO/Log/Filter/Suppress.php
new file mode 100644
index 000000000..fc801dd8e
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Filter/Suppress.php
@@ -0,0 +1,63 @@
+<?php
+/*
+ *  $Id: Suppress.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Filter_Suppress implements Doctrine_Log_Filter_Interface
+{
+    /**
+     * @var boolean
+     */
+    protected $_accept = true;
+
+    /**
+     * This is a simple boolean filter.
+     *
+     * Call suppress(true) to suppress all log events.
+     * Call suppress(false) to accept all log events.
+     *
+     * @param  boolean  $suppress  Should all log events be suppressed?
+     * @return  void
+     */
+    public function suppress($suppress)
+    {
+        $this->_accept = (! $suppress);
+    }
+
+    /**
+     * Returns TRUE to accept the message, FALSE to block it.
+     *
+     * @param  array    $event    event data
+     * @return boolean            accepted?
+     */
+    public function accept($event)
+    {
+        return $this->_accept;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Formatter/Interface.php b/lib/Doctrine/TODO/Log/Formatter/Interface.php
new file mode 100644
index 000000000..5a8494227
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Formatter/Interface.php
@@ -0,0 +1,41 @@
+<?php
+/*
+ *  $Id: Interface.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+interface Doctrine_Log_Formatter_Interface
+{
+    /**
+     * Formats data into a single line to be written by the writer.
+     *
+     * @param  array    $event    event data
+     * @return string             formatted line to write to the log
+     */
+    public function format($event);
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Formatter/Simple.php b/lib/Doctrine/TODO/Log/Formatter/Simple.php
new file mode 100644
index 000000000..b14ccff41
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Formatter/Simple.php
@@ -0,0 +1,72 @@
+<?php
+/*
+ *  $Id: Simple.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Formatter_Simple implements Doctrine_Log_Formatter_Interface
+{
+    /**
+     * @var string
+     */
+    protected $_format;
+
+    /**
+     * Class constructor
+     *
+     * @param  null|string  $format  Format specifier for log messages
+     * @throws Doctrine_Log_Exception
+     */
+    public function __construct($format = null)
+    {
+        if ($format === null) {
+            $format = '%timestamp% %priorityName% (%priority%): %message%' . PHP_EOL;
+        }
+
+        if (! is_string($format)) {
+            throw new Doctrine_Log_Exception('Format must be a string');
+        }
+
+        $this->_format = $format;
+    }
+
+    /**
+     * Formats data into a single line to be written by the writer.
+     *
+     * @param  array    $event    event data
+     * @return string             formatted line to write to the log
+     */
+    public function format($event)
+    {
+        $output = $this->_format;
+        foreach ($event as $name => $value) {
+            $output = str_replace("%$name%", $value, $output);
+        }
+        return $output;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Formatter/Xml.php b/lib/Doctrine/TODO/Log/Formatter/Xml.php
new file mode 100644
index 000000000..424f849d1
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Formatter/Xml.php
@@ -0,0 +1,84 @@
+<?php
+/*
+ *  $Id: Xml.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Formatter_Xml implements Doctrine_Log_Formatter_Interface
+{
+    /**
+     * @var Relates XML elements to log data field keys.
+     */
+    protected $_rootElement;
+
+    /**
+     * @var Relates XML elements to log data field keys.
+     */
+    protected $_elementMap;
+
+    /**
+     * Class constructor
+     *
+     * @param array $elementMap
+     */
+    public function __construct($rootElement = 'logEntry', $elementMap = null)
+    {
+        $this->_rootElement = $rootElement;
+        $this->_elementMap  = $elementMap;
+    }
+
+    /**
+     * Formats data into a single line to be written by the writer.
+     *
+     * @param  array    $event    event data
+     * @return string             formatted line to write to the log
+     */
+    public function format($event)
+    {
+        if ($this->_elementMap === null) {
+            $dataToInsert = $event;
+        } else {
+            $dataToInsert = array();
+            foreach ($this->_elementMap as $elementName => $fieldKey) {
+                $dataToInsert[$elementName] = $event[$fieldKey];
+            }
+        }
+
+        $dom = new DOMDocument();
+        $elt = $dom->appendChild(new DOMElement($this->_rootElement));
+
+        foreach ($dataToInsert as $key => $value) {
+            $elt->appendChild(new DOMElement($key, $value));
+        }
+
+        $xml = $dom->saveXML();
+        $xml = preg_replace('/<\?xml version="1.0"( encoding="[^\"]*")?\?>\n/u', '', $xml);
+
+        return $xml . PHP_EOL;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Writer/Abstract.php b/lib/Doctrine/TODO/Log/Writer/Abstract.php
new file mode 100644
index 000000000..7b83538c8
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Writer/Abstract.php
@@ -0,0 +1,103 @@
+<?php
+/*
+ *  $Id: Abstract.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+abstract class Doctrine_Log_Writer_Abstract
+{
+    /**
+     * @var array of Doctrine_Log_Filter_Interface
+     */
+    protected $_filters = array();
+
+    /**
+     * Formats the log message before writing.
+     * @var Doctrine_Log_Formatter_Interface
+     */
+    protected $_formatter;
+
+    /**
+     * Add a filter specific to this writer.
+     *
+     * @param  Doctrine_Log_Filter_Interface  $filter
+     * @return void
+     */
+    public function addFilter($filter)
+    {
+        if (is_integer($filter)) {
+            $filter = new Doctrine_Log_Filter_Priority($filter);
+        }
+
+        $this->_filters[] = $filter;
+    }
+
+    /**
+     * Log a message to this writer.
+     *
+     * @param  array     $event  log data event
+     * @return void
+     */
+    public function write($event)
+    {
+        foreach ($this->_filters as $filter) {
+            if (! $filter->accept($event)) {
+                return;
+            }
+        }
+
+        // exception occurs on error
+        $this->_write($event);
+    }
+
+    /**
+     * Set a new formatter for this writer
+     *
+     * @param  Doctrine_Log_Formatter_Interface $formatter
+     * @return void
+     */
+    public function setFormatter($formatter) {
+        $this->_formatter = $formatter;
+    }
+
+    /**
+     * Perform shutdown activites such as closing open resources
+     *
+     * @return void
+     */
+    public function shutdown()
+    {}
+
+    /**
+     * Write a message to the log.
+     *
+     * @param  array  $event  log data event
+     * @return void
+     */
+    abstract protected function _write($event);
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Writer/Db.php b/lib/Doctrine/TODO/Log/Writer/Db.php
new file mode 100644
index 000000000..88f52e087
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Writer/Db.php
@@ -0,0 +1,107 @@
+<?php
+/*
+ *  $Id: Db.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Writer_Db extends Doctrine_Log_Writer_Abstract
+{
+    /**
+     * Doctrine_Table instance
+     *
+     * @var string
+     */
+    private $_table;
+
+    /**
+     * Relates database columns names to log data field keys.
+     *
+     * @var null|array
+     */
+    private $_columnMap;
+
+    /**
+     * Class constructor
+     *
+     * @param Doctrine_Db_Adapter $db   Database adapter instance
+     * @param string $table         Log table in database
+     * @param array $columnMap
+     */
+    public function __construct($table, $columnMap = null)
+    {
+        if (!$table instanceof Doctrine_Table) {
+            $table = Doctrine::getTable($table);
+        }
+        
+        $this->_table = $table;
+        $this->_columnMap = $columnMap;
+    }
+
+    /**
+     * Formatting is not possible on this writer
+     */
+    public function setFormatter($formatter)
+    {
+        throw new Doctrine_Log_Exception(get_class() . ' does not support formatting');
+    }
+
+    /**
+     * Remove reference to database adapter
+     *
+     * @return void
+     */
+    public function shutdown()
+    {
+        $this->_table = null;
+    }
+
+    /**
+     * Write a message to the log.
+     *
+     * @param  array  $event  event data
+     * @return void
+     */
+    protected function _write($event)
+    {
+        if ($this->_table === null) {
+            throw new Doctrine_Log_Exception('Database adapter instance has been removed by shutdown');
+        }
+
+        if ($this->_columnMap === null) {
+            $dataToInsert = $event;
+        } else {
+            $dataToInsert = array();
+            foreach ($this->_columnMap as $columnName => $fieldKey) {
+                $dataToInsert[$columnName] = $event[$fieldKey];
+            }
+        }
+        
+        $record = $this->_table->create($dataToInsert);
+        $record->save();
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Writer/Mock.php b/lib/Doctrine/TODO/Log/Writer/Mock.php
new file mode 100644
index 000000000..e174f2c18
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Writer/Mock.php
@@ -0,0 +1,64 @@
+<?php
+/*
+ *  $Id: Mock.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Writer_Mock extends Doctrine_Log_Writer_Abstract
+{
+    /**
+     * array of log events
+     */
+    public $events = array();
+
+    /**
+     * shutdown called?
+     */
+    public $shutdown = false;
+
+    /**
+     * Write a message to the log.
+     *
+     * @param  array  $event  event data
+     * @return void
+     */
+    public function _write($event)
+    {
+        $this->events[] = $event;
+    }
+
+    /**
+     * Record shutdown
+     *
+     * @return void
+     */
+    public function shutdown()
+    {
+        $this->shutdown = true;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Writer/Null.php b/lib/Doctrine/TODO/Log/Writer/Null.php
new file mode 100644
index 000000000..02083b63d
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Writer/Null.php
@@ -0,0 +1,43 @@
+<?php
+/*
+ *  $Id: Null.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Writer_Null extends Doctrine_Log_Writer_Abstract
+{
+    /**
+     * Write a message to the log.
+     *
+     * @param  array  $event  event data
+     * @return void
+     */
+    protected function _write($event)
+    {
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Log/Writer/Stream.php b/lib/Doctrine/TODO/Log/Writer/Stream.php
new file mode 100644
index 000000000..510eea8a4
--- /dev/null
+++ b/lib/Doctrine/TODO/Log/Writer/Stream.php
@@ -0,0 +1,94 @@
+<?php
+/*
+ *  $Id: Stream.php 3155 2007-11-14 13:13:23Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * @package     Doctrine
+ * @subpackage  Log
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3155 $
+ */
+class Doctrine_Log_Writer_Stream extends Doctrine_Log_Writer_Abstract
+{
+    /**
+     * Holds the PHP stream to log to.
+     * @var null|stream
+     */
+    protected $_stream = null;
+
+    /**
+     * Class Constructor
+     *
+     * @param  streamOrUrl     Stream or URL to open as a stream
+     * @param  mode            Mode, only applicable if a URL is given
+     */
+    public function __construct($streamOrUrl, $mode = 'a')
+    {
+        if (is_resource($streamOrUrl)) {
+            if (get_resource_type($streamOrUrl) != 'stream') {
+                throw new Doctrine_Log_Exception('Resource is not a stream');
+            }
+
+            if ($mode != 'a') {
+                throw new Doctrine_Log_Exception('Mode cannot be changed on existing streams');
+            }
+
+            $this->_stream = $streamOrUrl;
+        } else {
+            if (! $this->_stream = @fopen($streamOrUrl, $mode, false)) {
+                $msg = "\"$streamOrUrl\" cannot be opened with mode \"$mode\"";
+                throw new Doctrine_Log_Exception($msg);
+            }
+        }
+
+        $this->_formatter = new Doctrine_Log_Formatter_Simple();
+    }
+
+    /**
+     * Close the stream resource.
+     *
+     * @return void
+     */
+    public function shutdown()
+    {
+        if (is_resource($this->_stream)) {
+            fclose($this->_stream);
+        }
+    }
+
+    /**
+     * Write a message to the log.
+     *
+     * @param  array  $event  event data
+     * @return void
+     */
+    protected function _write($event)
+    {
+        $line = $this->_formatter->format($event);
+
+        if (false === @fwrite($this->_stream, $line)) {
+            throw new Doctrine_Log_Exception("Unable to write to stream");
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Migration/Diff.php b/lib/Doctrine/TODO/Migration/Diff.php
new file mode 100644
index 000000000..81bde94ab
--- /dev/null
+++ b/lib/Doctrine/TODO/Migration/Diff.php
@@ -0,0 +1,155 @@
+<?php
+/*
+ *  $Id: Diff.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Migration_Diff
+ *
+ * @package     Doctrine
+ * @subpackage  Migration
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jonwage@gmail.com>
+ */
+class Doctrine_Migration_Diff
+{
+    protected $_from,
+              $_to,
+              $_changes = array(),
+              $_migrationsPath;
+
+    public function __construct($from = null, $to = null)
+    {
+        $this->_from = $from;
+        $this->_to = $to;
+    }
+
+    protected function getUniqueId()
+    {
+        return md5($this->_from.$this->_to);
+    }
+
+    public function setMigrationsPath($migrationsPath)
+    {
+        $this->_migrationsPath = $migrationsPath;
+    }
+
+    public function generate()
+    {
+        $from = $this->_generateModels('From', $this->_from);
+        $to = $this->_generateModels('To', $this->_to);
+
+        $differences = $this->_diff($from, $to);
+
+        print_r($differences);
+    }
+
+    protected function _diff($from, $to)
+    {
+        $fromTmpPath = sys_get_temp_dir() . $this->getUniqueId() . '_from';
+        $toTmpPath = sys_get_temp_dir() . $this->getUniqueId() . '_to';
+
+        if ( ! file_exists($fromTmpPath)) {
+            $fromModels = Doctrine::loadModels($from);
+            $fromInfo = $this->_buildModelInformation($fromModels);
+
+            file_put_contents($fromTmpPath, serialize($fromInfo));
+        } else {
+            if ( ! file_exists($toTmpPath)) {
+                $toModels = Doctrine::loadModels($to);
+                $toInfo = $this->_buildModelInformation($toModels);
+
+                file_put_contents($toTmpPath, serialize($toInfo));
+            } else {
+                $fromInfo = unserialize(file_get_contents($fromTmpPath));
+                $toInfo = unserialize(file_get_contents($toTmpPath));
+
+                $this->_buildChanges($fromInfo, $toInfo);
+
+                // clean up
+                unlink($fromTmpPath);
+                unlink($toTmpPath);
+                Doctrine_Lib::removeDirectories(sys_get_temp_dir() . 'from_doctrine_tmp_dirs');
+                Doctrine_Lib::removeDirectories(sys_get_temp_dir() . 'to_doctrine_tmp_dirs');
+            }
+        }
+    }
+    
+    protected function _buildChanges($from, $to)
+    {
+        foreach ($to as $key => $model) {
+            $columns = $model['columns'];
+            
+            foreach ($columns as $columnKey => $column) {
+                //if (isset($to[$key]['columns'][$columnKey]))
+            }
+        }
+    }
+
+    protected function _buildModelInformation(array $models)
+    {
+        $info = array();
+
+        foreach ($models as $key => $model) {
+            $info[$model] = Doctrine::getTable($model)->getExportableFormat();
+        }
+
+        return $info;
+    }
+
+    protected function _generateModels($prefix, $item)
+    {
+        $path = sys_get_temp_dir() . $prefix . '_doctrine_tmp_dirs';
+
+        if ( is_dir($item)) {
+            $files = glob($item . DIRECTORY_SEPARATOR . '*.*');
+
+            if (isset($files[0])) {
+                $pathInfo = pathinfo($files[0]);
+                $extension = $pathInfo['extension'];
+            }
+
+            if ($extension === 'yml') {
+                Doctrine::generateModelsFromYaml($item, $path);
+
+                return $path;
+            } else if ($extension === 'php') {
+
+                Doctrine_Lib::copyDirectory($item, $path);
+
+                return $path;
+            } else {
+                throw new Doctrine_Migration_Exception('No php or yml files found at path: "' . $item . '"');
+            }
+        } else {
+            try {
+                $connection = Doctrine_Manager::getInstance()->getConnection($item);
+
+                Doctrine::generateModelsFromDb($path, array($item));
+
+                return $path;
+            } catch (Exception $e) {
+                throw new Doctrine_Migration_Exception('Could not generate models from connection: ' . $e->getMessage());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Migration/Exception.php b/lib/Doctrine/TODO/Migration/Exception.php
new file mode 100644
index 000000000..9780241d0
--- /dev/null
+++ b/lib/Doctrine/TODO/Migration/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Migration_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Migration
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Migration_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Migration/IrreversibleMigrationException.php b/lib/Doctrine/TODO/Migration/IrreversibleMigrationException.php
new file mode 100644
index 000000000..14d5785bf
--- /dev/null
+++ b/lib/Doctrine/TODO/Migration/IrreversibleMigrationException.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: IrreversibleMigration.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Migration_IrreversibleMigration
+ *
+ * @package     Doctrine
+ * @subpackage  Migration
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Migration_IrreversibleMigrationException extends Doctrine_Migration_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Migration/Process.php b/lib/Doctrine/TODO/Migration/Process.php
new file mode 100644
index 000000000..58a552936
--- /dev/null
+++ b/lib/Doctrine/TODO/Migration/Process.php
@@ -0,0 +1,251 @@
+<?php
+/*
+ *  $Id: Process.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Migration_Process
+ *
+ * @package     Doctrine
+ * @subpackage  Migration
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Migration_Process
+{
+    /**
+     * getConnection
+     *
+     * @param string $tableName 
+     * @return void
+     */
+    public function getConnection($tableName)
+    {
+        return Doctrine::getConnectionByTableName($tableName);
+    }
+
+    /**
+     * processCreatedTables
+     *
+     * @param string $tables 
+     * @return void
+     */
+    public function processCreatedTables($tables)
+    {
+        foreach ($tables as $table) {
+            $conn = $this->getConnection($table['tableName']);
+            
+            $conn->export->createTable($table['tableName'], $table['fields'], $table['options']);
+        }
+    }
+
+    /**
+     * processDroppedTables
+     *
+     * @param string $tables 
+     * @return void
+     */
+    public function processDroppedTables($tables)
+    {
+        foreach ($tables as $table) {
+            $conn = $this->getConnection($table['tableName']);
+            
+            $conn->export->dropTable($table['tableName']);
+        }
+    }
+
+    /**
+     * processRenamedTables
+     *
+     * @param string $tables 
+     * @return void
+     */
+    public function processRenamedTables($tables)
+    {
+        foreach ($tables as $table) {
+            $conn = $this->getConnection($table['newTableName']);
+            
+            $conn->export->alterTable($table['oldTableName'], array('name' => $table['newTableName']));
+        }
+    }
+
+    /**
+     * processAddedColumns
+     *
+     * @param string $columns 
+     * @return void
+     */
+    public function processAddedColumns($columns)
+    {
+        foreach ($columns as $column) {
+            $conn = $this->getConnection($column['tableName']);
+            
+            $options = array();
+            $options = $column['options'];
+            $options['type'] = $column['type'];
+            
+            $conn->export->alterTable($column['tableName'], array('add' => array($column['columnName'] => $options)));
+        }
+    }
+
+    /**
+     * processRenamedColumns
+     *
+     * @param string $columns 
+     * @return void
+     */
+    public function processRenamedColumns($columns)
+    {
+        foreach ($columns as $column) {
+            $conn = $this->getConnection($column['tableName']);
+            
+            $columnList = $conn->import->listTableColumns($column['tableName']);
+            if (isset($columnList[$column['oldColumnName']])) {
+	            $conn->export->alterTable($column['tableName'], 
+	                                      array('rename' => array($column['oldColumnName'] => array('name' => $column['newColumnName'],
+	                                      																													'definition'=>$columnList[$column['oldColumnName']]))));
+            }
+        }
+    }
+
+    /**
+     * processChangedColumns
+     *
+     * @param string $columns 
+     * @return void
+     */
+    public function processChangedColumns($columns)
+    {
+        foreach ($columns as $column) {
+            $conn = $this->getConnection($column['tableName']);
+            
+            $options = array();
+            $options = $column['options'];
+            $options['type'] = $column['type'];
+            
+            $conn->export->alterTable($column['tableName'], array('change' => array($column['columnName'] => array('definition' => $options))));
+        }  
+    }
+
+    /**
+     * processRemovedColumns
+     *
+     * @param string $columns 
+     * @return void
+     */
+    public function processRemovedColumns($columns)
+    {
+        foreach ($columns as $column) {
+            $conn = $this->getConnection($column['tableName']);
+            
+            $conn->export->alterTable($column['tableName'], array('remove' => array($column['columnName'] => array())));
+        }
+    }
+
+    /**
+     * processAddexIndexes
+     *
+     * @param string $indexes 
+     * @return void
+     */
+    public function processAddedIndexes($indexes)
+    {
+        foreach ($indexes as $index) {
+            $conn = $this->getConnection($index['tableName']);
+            
+            $conn->export->createIndex($index['tableName'], $index['indexName'], $index['definition']);
+        }
+    }
+
+    /**
+     * processRemovedIndexes
+     *
+     * @param string $indexes 
+     * @return void
+     */
+    public function processRemovedIndexes($indexes)
+    {
+        foreach ($indexes as $index) {
+            $conn = $this->getConnection($index['tableName']);
+            
+            $conn->export->dropIndex($index['tableName'], $index['indexName']);
+        } 
+    }
+
+    /**
+     * processCreatedConstraints
+     *
+     * @param string $constraints 
+     * @return void
+     */
+    public function processCreatedConstraints($constraints)
+    {
+        foreach ($constraints as $constraint) {
+            $conn = $this->getConnection($constraint['tableName']);
+            $conn->export->createConstraint($constraint['tableName'], $constraint['constraintName'],
+                    $constraint['definition']);
+        }
+    }
+
+    /**
+     * processDroppedConstraints
+     *
+     * @param string $constraints 
+     * @return void
+     */
+    public function processDroppedConstraints($constraints)
+    {
+        foreach ($constraints as $constraint) {
+            $conn = $this->getConnection($constraint['tableName']);
+            $conn->export->dropConstraint($constraint['tableName'], $constraint['constraintName'],
+                    $constraint['primary']);
+        }
+    }
+
+    /**
+     * processCreatedFks
+     *
+     * @param string $foreignKeys 
+     * @return void
+     */
+    public function processCreatedFks($foreignKeys)
+    {
+        foreach ($foreignKeys as $fk) {
+            $conn = $this->getConnection($fk['tableName']);
+            $conn->export->createForeignKey($fk['tableName'], $fk['definition']);
+        }
+    }
+
+    /**
+     * processDroppedFks
+     *
+     * @param string $foreignKeys 
+     * @return void
+     */
+    public function processDroppedFks($foreignKeys)
+    {
+        foreach ($foreignKeys as $fk) {
+            $conn = $this->getConnection($fk['tableName']);
+            $conn->export->dropForeignKey($fk['tableName'], $fk['fkName']);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/AdjacencyList.php b/lib/Doctrine/TODO/Node/AdjacencyList.php
new file mode 100644
index 000000000..ff091e720
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/AdjacencyList.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: AdjacencyList.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_AdjacencyList
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_AdjacencyList extends Doctrine_Node implements Doctrine_Node_Interface
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/AdjacencyList/LevelOrderIterator.php b/lib/Doctrine/TODO/Node/AdjacencyList/LevelOrderIterator.php
new file mode 100644
index 000000000..c8d73bb7b
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/AdjacencyList/LevelOrderIterator.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: LevelOrderIterator.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_AdjacencyList_LevelOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_AdjacencyList_LevelOrderIterator implements Iterator
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/AdjacencyList/PostOrderIterator.php b/lib/Doctrine/TODO/Node/AdjacencyList/PostOrderIterator.php
new file mode 100644
index 000000000..bb56e79a5
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/AdjacencyList/PostOrderIterator.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: PostOrderIterator.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_AdjacencyList_PostOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_AdjacencyList_PostOrderIterator implements Iterator
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/AdjacencyList/PreOrderIterator.php b/lib/Doctrine/TODO/Node/AdjacencyList/PreOrderIterator.php
new file mode 100644
index 000000000..5d031fffc
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/AdjacencyList/PreOrderIterator.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: PreOrderIterator.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_AdjacencyList_PreOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_AdjacencyList_PreOrderIterator implements Iterator
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/Exception.php b/lib/Doctrine/TODO/Node/Exception.php
new file mode 100644
index 000000000..a16bc1847
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/Interface.php b/lib/Doctrine/TODO/Node/Interface.php
new file mode 100644
index 000000000..72ebeef05
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/Interface.php
@@ -0,0 +1,268 @@
+<?php
+/*
+ *  $Id: Interface.php 4364 2008-05-13 21:20:34Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_Interface
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 4364 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+interface Doctrine_Node_Interface {
+
+    /**
+     * test if node has previous sibling
+     *
+     * @return bool
+     */
+    public function hasPrevSibling();
+
+    /**
+     * test if node has next sibling
+     *
+     * @return bool
+     */
+    public function hasNextSibling();
+
+    /**
+     * test if node has children
+     *
+     * @return bool
+     */
+    public function hasChildren();
+
+    /**
+     * test if node has parent
+     *
+     * @return bool
+     */
+    public function hasParent();
+
+    /**
+     * gets record of prev sibling or empty record
+     *
+     * @return object Doctrine_Entity
+     */
+    public function getPrevSibling();
+
+    /**
+     * gets record of next sibling or empty record
+     *
+     * @return object Doctrine_Entity
+     */
+    public function getNextSibling();
+
+    /**
+     * gets siblings for node
+     *
+     * @return array                            array of sibling Doctrine_Entity objects
+     */
+    public function getSiblings($includeNode = false);
+
+    /**
+     * gets record of first child or empty record
+     *
+     * @return object Doctrine_Entity
+     */
+    public function getFirstChild();
+
+    /**
+     * gets record of last child or empty record
+     *
+     * @return object Doctrine_Entity
+     */
+    public function getLastChild();
+
+    /**
+     * gets children for node (direct descendants only)
+     *
+     * @return array                            array of sibling Doctrine_Entity objects
+     */
+    public function getChildren();
+
+    /**
+     * gets descendants for node (direct descendants only)
+     *
+     * @return iterator                         iterator to traverse descendants from node
+     */
+    public function getDescendants();
+
+    /**
+     * gets record of parent or empty record
+     *
+     * @return object Doctrine_Entity
+     */
+    public function getParent();
+
+    /**
+     * gets ancestors for node
+     *
+     * @return object Doctrine_Collection
+     */
+    public function getAncestors();
+
+    /**
+     * gets path to node from root, uses record::toString() method to get node names
+     *
+     * @param string $seperator                 path seperator
+     * @param bool $includeNode                 whether or not to include node at end of path
+     * @return string                           string representation of path
+     */
+    public function getPath($seperator = ' > ', $includeNode = false);
+
+    /**
+     * gets level (depth) of node in the tree
+     *
+     * @return int
+     */
+    public function getLevel();
+
+    /**
+     * gets number of children (direct descendants)
+     *
+     * @return int
+     */
+    public function getNumberChildren();
+
+    /**
+     * gets number of descendants (children and their children)
+     *
+     * @return int
+     */
+    public function getNumberDescendants();
+
+    /**
+     * inserts node as parent of dest record
+     *
+     * @return bool
+     */
+    public function insertAsParentOf(Doctrine_Entity $dest);
+
+    /**
+     * inserts node as previous sibling of dest record
+     *
+     * @return bool
+     */
+    public function insertAsPrevSiblingOf(Doctrine_Entity $dest);
+
+    /**
+     * inserts node as next sibling of dest record
+     *
+     * @return bool
+     */
+    public function insertAsNextSiblingOf(Doctrine_Entity $dest);
+
+    /**
+     * inserts node as first child of dest record
+     *
+     * @return bool
+     */
+    public function insertAsFirstChildOf(Doctrine_Entity $dest);
+
+    /**
+     * inserts node as first child of dest record
+     *
+     * @return bool
+     */
+    public function insertAsLastChildOf(Doctrine_Entity $dest);
+
+    /**
+     * moves node as prev sibling of dest record
+     *
+     */  
+    public function moveAsPrevSiblingOf(Doctrine_Entity $dest);
+
+    /**
+     * moves node as next sibling of dest record
+     *
+     */
+    public function moveAsNextSiblingOf(Doctrine_Entity $dest);
+
+    /**
+     * moves node as first child of dest record
+     *
+     */
+    public function moveAsFirstChildOf(Doctrine_Entity $dest);
+
+    /**
+     * moves node as last child of dest record
+     *
+     */
+    public function moveAsLastChildOf(Doctrine_Entity $dest);
+
+    /**
+     * adds node as last child of record
+     *
+     */
+    public function addChild(Doctrine_Entity $record);
+
+    /**
+     * determines if node is leaf
+     *
+     * @return bool
+     */
+    public function isLeaf();
+
+    /**
+     * determines if node is root
+     *
+     * @return bool
+     */
+    public function isRoot();
+
+    /**
+     * determines if node is equal to subject node
+     *
+     * @return bool
+     */
+    public function isEqualTo(Doctrine_Entity $subj);
+
+    /**
+     * determines if node is child of subject node
+     *
+     * @return bool
+     */
+    public function isDescendantOf(Doctrine_Entity $subj);
+
+    /**
+     * determines if node is child of or sibling to subject node
+     *
+     * @return bool
+     */
+    public function isDescendantOfOrEqualTo(Doctrine_Entity $subj);
+
+    /**
+     * determines if node is valid
+     *
+     * @return bool
+     */
+    public function isValidNode();
+
+    /**
+     * deletes node and it's descendants
+     *
+     */
+    public function delete();
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/MaterializedPath.php b/lib/Doctrine/TODO/Node/MaterializedPath.php
new file mode 100644
index 000000000..e1b3aa867
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/MaterializedPath.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: MaterializedPath.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_MaterializedPath
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Node_MaterializedPath extends Doctrine_Node implements Doctrine_Node_Interface
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/MaterializedPath/LevelOrderIterator.php b/lib/Doctrine/TODO/Node/MaterializedPath/LevelOrderIterator.php
new file mode 100644
index 000000000..a92130f49
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/MaterializedPath/LevelOrderIterator.php
@@ -0,0 +1,68 @@
+<?php
+/*
+ *  $Id: LevelOrderIterator.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_MaterializedPath_LevelOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_MaterializedPath_LevelOrderIterator implements Iterator
+{
+    private $topNode = null;
+
+    private $curNode = null;
+
+    public function __construct($node, $opts)
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function rewind()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function valid()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function current()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function key()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function next()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/MaterializedPath/PostOrderIterator.php b/lib/Doctrine/TODO/Node/MaterializedPath/PostOrderIterator.php
new file mode 100644
index 000000000..2e26cc603
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/MaterializedPath/PostOrderIterator.php
@@ -0,0 +1,68 @@
+<?php
+/*
+ *  $Id: PostOrderIterator.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_MaterializedPath_PostOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_MaterializedPath_PostOrderIterator implements Iterator
+{
+    private $topNode = null;
+
+    private $curNode = null;
+
+    public function __construct($node, $opts)
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function rewind()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function valid()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function current()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function key()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function next()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/MaterializedPath/PreOrderIterator.php b/lib/Doctrine/TODO/Node/MaterializedPath/PreOrderIterator.php
new file mode 100644
index 000000000..540f319c2
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/MaterializedPath/PreOrderIterator.php
@@ -0,0 +1,68 @@
+<?php
+/*
+ *  $Id: PreOrderIterator.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_MaterializedPath_PreOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_MaterializedPath_PreOrderIterator implements Iterator
+{
+    private $topNode = null;
+
+    private $curNode = null;
+
+    public function __construct($node, $opts)
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function rewind()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function valid()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function current()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function key()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+
+    public function next()
+    {
+        throw new Doctrine_Exception('Not yet implemented');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/NestedSet.php b/lib/Doctrine/TODO/Node/NestedSet.php
new file mode 100644
index 000000000..892549594
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/NestedSet.php
@@ -0,0 +1,1009 @@
+<?php
+/*
+ *    $Id: NestedSet.php 4364 2008-05-13 21:20:34Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_NestedSet
+ *
+ * @package    Doctrine
+ * @subpackage Node
+ * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link       www.phpdoctrine.org
+ * @since      1.0
+ * @version    $Revision: 4364 $
+ * @author     Joe Simms <joe.simms@websites4.com>
+ * @author     Roman Borschel <roman@code-factory.org>     
+ */
+class Doctrine_Node_NestedSet extends Doctrine_Node implements Doctrine_Node_Interface
+{
+    /**
+     * test if node has previous sibling
+     *
+     * @return bool            
+     */
+    public function hasPrevSibling()
+    {
+        return $this->isValidNode($this->getPrevSibling());        
+    }
+
+    /**
+     * test if node has next sibling
+     *
+     * @return bool            
+     */ 
+    public function hasNextSibling()
+    {
+        return $this->isValidNode($this->getNextSibling());        
+    }
+
+    /**
+     * test if node has children
+     *
+     * @return bool            
+     */
+    public function hasChildren()
+    {
+        return (($this->getRightValue() - $this->getLeftValue()) > 1);        
+    }
+
+    /**
+     * test if node has parent
+     *
+     * @return bool            
+     */
+    public function hasParent()
+    {
+        return !$this->isRoot();
+    }
+
+    /**
+     * gets record of prev sibling or empty record
+     *
+     * @return object     Doctrine_Entity            
+     */
+    public function getPrevSibling()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q = $q->addWhere("$baseAlias.rgt = ?", $this->getLeftValue() - 1);
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+        
+        if ($result instanceof Doctrine_Collection) {
+            $sibling = $result->getFirst();
+        } else if (is_array($result)) {
+            $sibling = array_shift($result);
+        }
+        
+        return $sibling;
+    }
+
+    /**
+     * gets record of next sibling or empty record
+     *
+     * @return object     Doctrine_Entity            
+     */
+    public function getNextSibling()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q = $q->addWhere("$baseAlias.lft = ?", $this->getRightValue() + 1);
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+        
+        if ($result instanceof Doctrine_Collection) {
+            $sibling = $result->getFirst();
+        } else if (is_array($result)) {
+            $sibling = array_shift($result);
+        }
+        
+        return $sibling;
+    }
+
+    /**
+     * gets siblings for node
+     *
+     * @return array     array of sibling Doctrine_Entity objects            
+     */
+    public function getSiblings($includeNode = false)
+    {
+        $parent = $this->getParent();
+        $siblings = array();
+        if ($parent->exists()) {
+            foreach ($parent->getNode()->getChildren() as $child) {
+                if ($this->isEqualTo($child) && !$includeNode) {
+                    continue;
+                }
+                $siblings[] = $child;
+            }        
+        }
+        return $siblings;
+    }
+
+    /**
+     * gets record of first child or empty record
+     *
+     * @return object     Doctrine_Entity            
+     */
+    public function getFirstChild()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q->addWhere("$baseAlias.lft = ?", $this->getLeftValue() + 1);
+        $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+        
+        if ($result instanceof Doctrine_Collection) {
+            $child = $result->getFirst();
+        } else if (is_array($result)) {
+            $child = array_shift($result);
+        }
+        
+        return $child;       
+    }
+
+    /**
+     * gets record of last child or empty record
+     *
+     * @return object     Doctrine_Entity            
+     */
+    public function getLastChild()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q->addWhere("$baseAlias.rgt = ?", $this->getRightValue() - 1);
+        $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+        
+        if ($result instanceof Doctrine_Collection) {
+            $child = $result->getFirst();
+        } else if (is_array($result)) {
+            $child = array_shift($result);
+        }
+        
+        return $child;      
+    }
+
+    /**
+     * gets children for node (direct descendants only)
+     *
+     * @return mixed The children of the node or FALSE if the node has no children.               
+     */
+    public function getChildren()
+    { 
+        return $this->getDescendants(1);
+    }
+
+    /**
+     * gets descendants for node (direct descendants only)
+     *
+     * @return mixed  The descendants of the node or FALSE if the node has no descendants.
+     * @todo Currently all descendants are fetched, no matter the depth. Maybe there is a better
+     *       solution with less overhead.      
+     */
+    public function getDescendants($depth = null, $includeNode = false)
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $params = array($this->record->get('lft'), $this->record->get('rgt'));
+        
+        if ($includeNode) {
+            $q->addWhere("$baseAlias.lft >= ? AND $baseAlias.rgt <= ?", $params)->addOrderBy("$baseAlias.lft asc");
+        } else {
+            $q->addWhere("$baseAlias.lft > ? AND $baseAlias.rgt < ?", $params)->addOrderBy("$baseAlias.lft asc");
+        }
+        
+        if ($depth !== null) {
+            $q->addWhere("$baseAlias.level <= ?", $this->record['level'] + $depth);
+        }
+        
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+
+        if (count($result) <= 0) {
+            return false;
+        }
+
+        return $result;
+    }
+
+    /**
+     * gets record of parent or empty record
+     *
+     * @return object     Doctrine_Entity            
+     */
+    public function getParent()
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q->addWhere("$baseAlias.lft < ? AND $baseAlias.rgt > ?", array($this->getLeftValue(), $this->getRightValue()))
+                ->addOrderBy("$baseAlias.rgt asc");
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $result = $q->execute();
+        
+        if (count($result) <= 0) {
+            return false;
+        }
+               
+        if ($result instanceof Doctrine_Collection) {
+            $parent = $result->getFirst();
+        } else if (is_array($result)) {
+            $parent = array_shift($result);
+        }
+        
+        return $parent;
+    }
+
+    /**
+     * gets ancestors for node
+     *
+     * @param integer $deth  The depth 'upstairs'.
+     * @return mixed  The ancestors of the node or FALSE if the node has no ancestors (this 
+     *                basically means it's a root node).                
+     */
+    public function getAncestors($depth = null)
+    {
+        $baseAlias = $this->_tree->getBaseAlias();
+        $q = $this->_tree->getBaseQuery();
+        $q->addWhere("$baseAlias.lft < ? AND $baseAlias.rgt > ?", array($this->getLeftValue(), $this->getRightValue()))
+                ->addOrderBy("$baseAlias.lft asc");
+        if ($depth !== null) {
+            $q->addWhere("$baseAlias.level >= ?", $this->record['level'] - $depth);
+        }
+        $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+        $ancestors = $q->execute();
+        if (count($ancestors) <= 0) {
+            return false;
+        }
+        return $ancestors;
+    }
+
+    /**
+     * gets path to node from root, uses record::toString() method to get node names
+     *
+     * @param string     $seperator     path seperator
+     * @param bool     $includeNode     whether or not to include node at end of path
+     * @return string     string representation of path                
+     */     
+    public function getPath($seperator = ' > ', $includeRecord = false)
+    {
+        $path = array();
+        $ancestors = $this->getAncestors();
+        if ($ancestors) {
+            foreach ($ancestors as $ancestor) {
+                $path[] = $ancestor->__toString();
+            }
+        }
+        if ($includeRecord) {
+            $path[] = $this->getRecord()->__toString();
+        }
+            
+        return implode($seperator, $path);
+    }
+
+    /**
+     * gets number of children (direct descendants)
+     *
+     * @return int            
+     */     
+    public function getNumberChildren()
+    {
+        return count($this->getChildren());
+    }
+
+    /**
+     * gets number of descendants (children and their children)
+     *
+     * @return int            
+     */
+    public function getNumberDescendants()
+    {
+        return ($this->getRightValue() - $this->getLeftValue() - 1) / 2;
+    }
+
+    /**
+     * inserts node as parent of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction          
+     */
+    public function insertAsParentOf(Doctrine_Entity $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode()) {
+            return false;
+        }
+        // cannot insert as parent of root
+        if ($dest->getNode()->isRoot()) {
+            return false;
+        }
+        
+        $newLeft  = $dest->getNode()->getLeftValue();
+        $newRight = $dest->getNode()->getRightValue() + 2;
+        $newRoot  = $dest->getNode()->getRootValue();
+		$newLevel = $dest->getNode()->getLevel();
+		
+		// Make space for new node
+        $this->shiftRLValues($dest->getNode()->getRightValue() + 1, 2, $newRoot);
+        
+        // Slide child nodes over one and down one to allow new parent to wrap them
+		$componentName = $this->_tree->getBaseComponent();		
+        $q = new Doctrine_Query();
+        $q->update($componentName);
+        $q->set("$componentName.lft", "$componentName.lft + 1");
+        $q->set("$componentName.rgt", "$componentName.rgt + 1");
+        $q->set("$componentName.level", "$componentName.level + 1");
+        $q->where("$componentName.lft >= ? AND $componentName.rgt <= ?", array($newLeft, $newRight));
+		$q = $this->_tree->returnQueryWithRootId($q, $newRoot);
+		$q->execute();
+        
+        $this->record['level'] = $newLevel;
+		$this->insertNode($newLeft, $newRight, $newRoot);
+        
+        return true;
+    }
+
+    /**
+     * inserts node as previous sibling of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction       
+     */
+    public function insertAsPrevSiblingOf(Doctrine_Entity $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode())
+            return false;
+
+        $newLeft = $dest->getNode()->getLeftValue();
+        $newRight = $dest->getNode()->getLeftValue() + 1;
+        $newRoot = $dest->getNode()->getRootValue();
+        
+        $this->shiftRLValues($newLeft, 2, $newRoot);
+        $this->record['level'] = $dest['level'];
+        $this->insertNode($newLeft, $newRight, $newRoot);
+        // update destination left/right values to prevent a refresh
+        // $dest->getNode()->setLeftValue($dest->getNode()->getLeftValue() + 2);
+        // $dest->getNode()->setRightValue($dest->getNode()->getRightValue() + 2);
+                        
+        return true;
+    }
+
+    /**
+     * inserts node as next sibling of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction           
+     */    
+    public function insertAsNextSiblingOf(Doctrine_Entity $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode())
+            return false;
+
+        $newLeft = $dest->getNode()->getRightValue() + 1;
+        $newRight = $dest->getNode()->getRightValue() + 2;
+        $newRoot = $dest->getNode()->getRootValue();
+
+        $this->shiftRLValues($newLeft, 2, $newRoot);
+        $this->record['level'] = $dest['level'];
+        $this->insertNode($newLeft, $newRight, $newRoot);
+
+        // update destination left/right values to prevent a refresh
+        // no need, node not affected
+
+        return true;
+    }
+
+    /**
+     * inserts node as first child of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction         
+     */
+    public function insertAsFirstChildOf(Doctrine_Entity $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode())
+            return false;
+
+        $newLeft = $dest->getNode()->getLeftValue() + 1;
+        $newRight = $dest->getNode()->getLeftValue() + 2;
+        $newRoot = $dest->getNode()->getRootValue();
+
+        $this->shiftRLValues($newLeft, 2, $newRoot);
+        $this->record['level'] = $dest['level'] + 1;
+        $this->insertNode($newLeft, $newRight, $newRoot);
+        
+        // update destination left/right values to prevent a refresh
+        // $dest->getNode()->setRightValue($dest->getNode()->getRightValue() + 2);
+
+        return true;
+    }
+
+    /**
+     * inserts node as last child of dest record
+     *
+     * @return bool
+     * @todo Wrap in transaction            
+     */
+    public function insertAsLastChildOf(Doctrine_Entity $dest)
+    {
+        // cannot insert a node that has already has a place within the tree
+        if ($this->isValidNode())
+            return false;
+
+        $newLeft = $dest->getNode()->getRightValue();
+        $newRight = $dest->getNode()->getRightValue() + 1;
+        $newRoot = $dest->getNode()->getRootValue();
+
+        $this->shiftRLValues($newLeft, 2, $newRoot);
+        $this->record['level'] = $dest['level'] + 1;
+        $this->insertNode($newLeft, $newRight, $newRoot);
+
+        // update destination left/right values to prevent a refresh
+        // $dest->getNode()->setRightValue($dest->getNode()->getRightValue() + 2);
+        
+        return true;
+    }
+
+    /**
+     * Accomplishes moving of nodes between different trees.
+     * Used by the move* methods if the root values of the two nodes are different.
+     *
+     * @param Doctrine_Entity $dest
+     * @param unknown_type $newLeftValue
+     * @param unknown_type $moveType
+     * @todo Better exception handling/wrapping
+     */
+    private function _moveBetweenTrees(Doctrine_Entity $dest, $newLeftValue, $moveType)
+    {
+        $conn = $this->record->getTable()->getConnection();
+            
+            try {
+                $conn->beginTransaction();
+                
+                // Move between trees: Detach from old tree & insert into new tree
+                $newRoot = $dest->getNode()->getRootValue();
+                $oldRoot = $this->getRootValue();
+                $oldLft = $this->getLeftValue();
+                $oldRgt = $this->getRightValue();
+                $oldLevel = $this->record['level'];
+                
+                // Prepare target tree for insertion, make room
+                $this->shiftRlValues($newLeftValue, $oldRgt - $oldLft - 1, $newRoot);
+                
+                // Set new root id for this node
+                $this->setRootValue($newRoot);
+                $this->record->save();
+                
+                // Close gap in old tree
+                $first = $oldRgt + 1;
+                $delta = $oldLft - $oldRgt - 1;
+                $this->shiftRLValues($first, $delta, $oldRoot);
+                
+                // Insert this node as a new node
+                $this->setRightValue(0);
+                $this->setLeftValue(0);
+                
+                switch ($moveType) {
+                    case 'moveAsPrevSiblingOf':
+                        $this->insertAsPrevSiblingOf($dest);
+                    break;
+                    case 'moveAsFirstChildOf':
+                        $this->insertAsFirstChildOf($dest);
+                    break;
+                    case 'moveAsNextSiblingOf':
+                        $this->insertAsNextSiblingOf($dest);
+                    break;
+                    case 'moveAsLastChildOf':
+                        $this->insertAsLastChildOf($dest);
+                    break;
+                    default:
+                        throw new Exception("Unknown move operation: $moveType.");
+                }
+                
+                $diff = $oldRgt - $oldLft;
+                $this->setRightValue($this->getLeftValue() + ($oldRgt - $oldLft));
+                $this->record->save();
+                
+                $newLevel = $this->record['level'];
+                $levelDiff = $newLevel - $oldLevel;
+                
+                // Relocate descendants of the node
+                $diff = $this->getLeftValue() - $oldLft;
+                $componentName = $this->_tree->getBaseComponent();
+                $rootColName = $this->_tree->getAttribute('rootColumnName');
+
+                // Update lft/rgt/root/level for all descendants
+                $q = new Doctrine_Query($conn);
+                $q = $q->update($componentName)
+                        ->set($componentName . '.lft', 'lft + ?', $diff)
+                        ->set($componentName . '.rgt', 'rgt + ?', $diff)
+                        ->set($componentName . '.level', 'level + ?', $levelDiff)
+                        ->set($componentName . '.' . $rootColName, '?', $newRoot)
+                        ->where($componentName . '.lft > ? AND ' . $componentName . '.rgt < ?',
+                        array($oldLft, $oldRgt));
+                $q = $this->_tree->returnQueryWithRootId($q, $oldRoot);
+                $q->execute();
+                
+                $conn->commit();
+            } catch (Exception $e) {
+                $conn->rollback();
+                throw $e;
+            }
+    }
+
+    /**
+     * moves node as prev sibling of dest record
+     * 
+     */     
+    public function moveAsPrevSiblingOf(Doctrine_Entity $dest)
+    {
+        if ($dest->getNode()->getRootValue() != $this->getRootValue()) {
+            // Move between trees
+            $this->_moveBetweenTrees($dest, $dest->getNode()->getLeftValue(), __FUNCTION__);
+        } else {
+            // Move within the tree
+            $oldLevel = $this->record['level'];
+            $this->record['level'] = $dest['level'];
+            $this->updateNode($dest->getNode()->getLeftValue(), $this->record['level'] - $oldLevel);
+        }
+    }
+
+    /**
+     * moves node as next sibling of dest record
+     *        
+     */
+    public function moveAsNextSiblingOf(Doctrine_Entity $dest)
+    {
+        if ($dest->getNode()->getRootValue() != $this->getRootValue()) {
+            // Move between trees
+            $this->_moveBetweenTrees($dest, $dest->getNode()->getRightValue() + 1, __FUNCTION__);
+        } else {
+            // Move within tree
+            $oldLevel = $this->record['level'];
+            $this->record['level'] = $dest['level'];
+            $this->updateNode($dest->getNode()->getRightValue() + 1, $this->record['level'] - $oldLevel);
+        }
+    }
+
+    /**
+     * moves node as first child of dest record
+     *            
+     */
+    public function moveAsFirstChildOf(Doctrine_Entity $dest)
+    {
+        if ($dest->getNode()->getRootValue() != $this->getRootValue()) {
+            // Move between trees
+            $this->_moveBetweenTrees($dest, $dest->getNode()->getLeftValue() + 1, __FUNCTION__);
+        } else {
+            // Move within tree
+            $oldLevel = $this->record['level'];
+            $this->record['level'] = $dest['level'] + 1;
+            $this->updateNode($dest->getNode()->getLeftValue() + 1, $this->record['level'] - $oldLevel);
+        }
+    }
+
+    /**
+     * moves node as last child of dest record
+     *        
+     */
+    public function moveAsLastChildOf(Doctrine_Entity $dest)
+    {
+        if ($dest->getNode()->getRootValue() != $this->getRootValue()) {
+            // Move between trees
+            $this->_moveBetweenTrees($dest, $dest->getNode()->getRightValue(), __FUNCTION__);
+        } else {
+            // Move within tree
+            $oldLevel = $this->record['level'];
+            $this->record['level'] = $dest['level'] + 1;
+            $this->updateNode($dest->getNode()->getRightValue(), $this->record['level'] - $oldLevel);
+        }
+    }
+
+    /**
+     * Makes this node a root node. Only used in multiple-root trees.
+     *
+     * @todo Exception handling/wrapping
+     */
+    public function makeRoot($newRootId)
+    {
+        // TODO: throw exception instead?
+        if ($this->getLeftValue() == 1 || ! $this->_tree->getAttribute('hasManyRoots')) {
+            return false;
+        }
+        
+        $oldRgt = $this->getRightValue();
+        $oldLft = $this->getLeftValue();
+        $oldRoot = $this->getRootValue();
+        $oldLevel = $this->record['level'];
+        
+        try {
+            $conn = $this->record->getTable()->getConnection();
+            $conn->beginTransaction();
+            
+            // Detach from old tree (close gap in old tree)
+            $first = $oldRgt + 1;
+            $delta = $oldLft - $oldRgt - 1;
+            $this->shiftRLValues($first, $delta, $this->getRootValue());
+            
+            // Set new lft/rgt/root/level values for root node
+            $this->setLeftValue(1);
+            $this->setRightValue($oldRgt - $oldLft + 1);
+            $this->setRootValue($newRootId);
+            $this->record['level'] = 0;
+            
+            // Update descendants lft/rgt/root/level values
+            $diff = 1 - $oldLft;
+            $newRoot = $newRootId;
+            $componentName = $this->_tree->getBaseComponent();
+            $rootColName = $this->_tree->getAttribute('rootColumnName');
+            $q = new Doctrine_Query($conn);
+            $q = $q->update($componentName)
+                    ->set($componentName . '.lft', 'lft + ?', $diff)
+                    ->set($componentName . '.rgt', 'rgt + ?', $diff)
+                    ->set($componentName . '.level', 'level - ?', $oldLevel)
+                    ->set($componentName . '.' . $rootColName, '?', $newRoot)
+                    ->where($componentName . '.lft > ? AND ' . $componentName . '.rgt < ?',
+                    array($oldLft, $oldRgt));
+            $q = $this->_tree->returnQueryWithRootId($q, $oldRoot);
+            $q->execute();
+            
+            $conn->commit();
+            
+        } catch (Exception $e) {
+            $conn->rollback();
+            throw $e;
+        }
+    }
+
+    /**
+     * adds node as last child of record
+     *        
+     */
+    public function addChild(Doctrine_Entity $record)
+    {
+        $record->getNode()->insertAsLastChildOf($this->getRecord());
+    }
+
+    /**
+     * determines if node is leaf
+     *
+     * @return bool            
+     */
+    public function isLeaf()
+    {
+        return (($this->getRightValue() - $this->getLeftValue()) == 1);
+    }
+
+    /**
+     * determines if node is root
+     *
+     * @return bool            
+     */
+    public function isRoot()
+    {
+        return ($this->getLeftValue() == 1);
+    }
+
+    /**
+     * determines if node is equal to subject node
+     *
+     * @return bool            
+     */    
+    public function isEqualTo(Doctrine_Entity $subj)
+    {
+        return (($this->getLeftValue() == $subj->getNode()->getLeftValue()) &&
+                ($this->getRightValue() == $subj->getNode()->getRightValue()) && 
+                ($this->getRootValue() == $subj->getNode()->getRootValue())
+                );
+    }
+
+    /**
+     * determines if node is child of subject node
+     *
+     * @return bool
+     */
+    public function isDescendantOf(Doctrine_Entity $subj)
+    {
+        return (($this->getLeftValue() > $subj->getNode()->getLeftValue()) &&
+                ($this->getRightValue() < $subj->getNode()->getRightValue()) &&
+                ($this->getRootValue() == $subj->getNode()->getRootValue()));
+    }
+
+    /**
+     * determines if node is child of or sibling to subject node
+     *
+     * @return bool            
+     */
+    public function isDescendantOfOrEqualTo(Doctrine_Entity $subj)
+    {
+        return (($this->getLeftValue() >= $subj->getNode()->getLeftValue()) &&
+                ($this->getRightValue() <= $subj->getNode()->getRightValue()) &&
+                ($this->getRootValue() == $subj->getNode()->getRootValue()));
+    }
+
+    /**
+     * determines if node is valid
+     *
+     * @return bool
+     */
+    public function isValidNode($record = null)
+    {
+        if ($record === null) {
+          return ($this->getRightValue() > $this->getLeftValue());
+        } else if ( $record instanceof Doctrine_Entity ) {
+          return ($record->getNode()->getRightValue() > $record->getNode()->getLeftValue());
+        } else {
+          return false;
+        }
+    }
+
+    /**
+     * deletes node and it's descendants
+     * @todo Delete more efficiently. Wrap in transaction if needed.      
+     */
+    public function delete()
+    {
+        // TODO: add the setting whether or not to delete descendants or relocate children
+        $oldRoot = $this->getRootValue();
+        $q = $this->_tree->getBaseQuery();
+        
+        $baseAlias = $this->_tree->getBaseAlias();
+        $componentName = $this->_tree->getBaseComponent();
+
+        $q = $q->addWhere("$baseAlias.lft >= ? AND $baseAlias.rgt <= ?", array($this->getLeftValue(), $this->getRightValue()));
+
+        $q = $this->_tree->returnQueryWithRootId($q, $oldRoot);
+        
+        $coll = $q->execute();
+
+        $coll->delete();
+
+        $first = $this->getRightValue() + 1;
+        $delta = $this->getLeftValue() - $this->getRightValue() - 1;
+        $this->shiftRLValues($first, $delta, $oldRoot);
+        
+        return true; 
+    }
+
+    /**
+     * sets node's left and right values and save's it
+     *
+     * @param int     $destLeft     node left value
+     * @param int        $destRight    node right value
+     */    
+    private function insertNode($destLeft = 0, $destRight = 0, $destRoot = 1)
+    {
+        $this->setLeftValue($destLeft);
+        $this->setRightValue($destRight);
+        $this->setRootValue($destRoot);
+        $this->record->save();    
+    }
+
+    /**
+     * move node's and its children to location $destLeft and updates rest of tree
+     *
+     * @param int     $destLeft    destination left value
+     * @todo Wrap in transaction
+     */
+    private function updateNode($destLeft, $levelDiff)
+    { 
+        $componentName = $this->_tree->getBaseComponent();
+        $left = $this->getLeftValue();
+        $right = $this->getRightValue();
+        $rootId = $this->getRootValue();
+
+        $treeSize = $right - $left + 1;
+
+        // Make room in the new branch
+        $this->shiftRLValues($destLeft, $treeSize, $rootId);
+
+        if ($left >= $destLeft) { // src was shifted too?
+            $left += $treeSize;
+            $right += $treeSize;
+        }
+
+        // update level for descendants
+        $q = new Doctrine_Query();
+        $q = $q->update($componentName)
+                ->set($componentName . '.level', 'level + ?')
+                ->where($componentName . '.lft > ? AND ' . $componentName . '.rgt < ?',
+                        array($levelDiff, $left, $right));
+        $q = $this->_tree->returnQueryWithRootId($q, $rootId);
+        $q->execute();
+        
+        // now there's enough room next to target to move the subtree
+        $this->shiftRLRange($left, $right, $destLeft - $left, $rootId);
+
+        // correct values after source (close gap in old tree)
+        $this->shiftRLValues($right + 1, -$treeSize, $rootId);
+
+        $this->record->save();
+        $this->record->refresh();
+    }
+
+    /**
+     * adds '$delta' to all Left and Right values that are >= '$first'. '$delta' can also be negative.
+     *
+     * @param int $first         First node to be shifted
+     * @param int $delta         Value to be shifted by, can be negative
+     */    
+    private function shiftRlValues($first, $delta, $rootId = 1)
+    {
+        $qLeft  = new Doctrine_Query();
+        $qRight = new Doctrine_Query();
+
+        // shift left columns
+        $componentName = $this->_tree->getBaseComponent();
+        $qLeft = $qLeft->update($componentName)
+                                ->set($componentName . '.lft', 'lft + ?')
+                                ->where($componentName . '.lft >= ?', array($delta, $first));
+        
+        $qLeft = $this->_tree->returnQueryWithRootId($qLeft, $rootId);
+        
+        $resultLeft = $qLeft->execute();
+        
+        // shift right columns
+        $resultRight = $qRight->update($componentName)
+                                ->set($componentName . '.rgt', 'rgt + ?')
+                                ->where($componentName . '.rgt >= ?', array($delta, $first));
+
+        $qRight = $this->_tree->returnQueryWithRootId($qRight, $rootId);
+
+        $resultRight = $qRight->execute();
+    }
+
+    /**
+     * adds '$delta' to all Left and Right values that are >= '$first' and <= '$last'. 
+     * '$delta' can also be negative.
+     *
+     * @param int $first     First node to be shifted (L value)
+     * @param int $last     Last node to be shifted (L value)
+     * @param int $delta         Value to be shifted by, can be negative
+     */ 
+    private function shiftRlRange($first, $last, $delta, $rootId = 1)
+    {
+        $qLeft  = new Doctrine_Query();
+        $qRight = new Doctrine_Query();
+
+        // shift left column values
+        $componentName = $this->_tree->getBaseComponent();
+        $qLeft = $qLeft->update($componentName)
+                                ->set($componentName . '.lft', 'lft + ?')
+                                ->where($componentName . '.lft >= ? AND ' . $componentName . '.lft <= ?', array($delta, $first, $last));
+        
+        $qLeft = $this->_tree->returnQueryWithRootId($qLeft, $rootId);
+
+        $resultLeft = $qLeft->execute();
+        
+        // shift right column values
+        $qRight = $qRight->update($componentName)
+                                ->set($componentName . '.rgt', 'rgt + ?')
+                                ->where($componentName . '.rgt >= ? AND ' . $componentName . '.rgt <= ?', array($delta, $first, $last));
+
+        $qRight = $this->_tree->returnQueryWithRootId($qRight, $rootId);
+
+        $resultRight = $qRight->execute();
+    }
+
+    /**
+     * gets record's left value
+     *
+     * @return int            
+     */     
+    public function getLeftValue()
+    {
+        return $this->record->get('lft');
+    }
+
+    /**
+     * sets record's left value
+     *
+     * @param int            
+     */     
+    public function setLeftValue($lft)
+    {
+        $this->record->set('lft', $lft);        
+    }
+
+    /**
+     * gets record's right value
+     *
+     * @return int            
+     */     
+    public function getRightValue()
+    {
+        return $this->record->get('rgt');        
+    }
+
+    /**
+     * sets record's right value
+     *
+     * @param int            
+     */    
+    public function setRightValue($rgt)
+    {
+        $this->record->set('rgt', $rgt);         
+    }
+
+    /**
+     * gets level (depth) of node in the tree
+     *
+     * @return int            
+     */    
+    public function getLevel()
+    {
+        if ( ! isset($this->record['level'])) {
+            $baseAlias = $this->_tree->getBaseAlias();
+            $componentName = $this->_tree->getBaseComponent();
+            $q = $this->_tree->getBaseQuery();
+            $q = $q->addWhere("$baseAlias.lft < ? AND $baseAlias.rgt > ?", array($this->getLeftValue(), $this->getRightValue()));
+
+            $q = $this->_tree->returnQueryWithRootId($q, $this->getRootValue());
+            
+            $coll = $q->execute();
+
+            $this->record['level'] = count($coll) ? count($coll) : 0;
+        }
+        return $this->record['level'];
+    }
+
+    /**
+     * get records root id value
+     *            
+     */     
+    public function getRootValue()
+    {
+        if ($this->_tree->getAttribute('hasManyRoots')) {
+            return $this->record->get($this->_tree->getAttribute('rootColumnName'));
+        }
+        return 1;
+    }
+
+    /**
+     * sets records root id value
+     *
+     * @param int            
+     */
+    public function setRootValue($value)
+    {
+        if ($this->_tree->getAttribute('hasManyRoots')) {
+            $this->record->set($this->_tree->getAttribute('rootColumnName'), $value);   
+        }    
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/NestedSet/LevelOrderIterator.php b/lib/Doctrine/TODO/Node/NestedSet/LevelOrderIterator.php
new file mode 100644
index 000000000..92110f08e
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/NestedSet/LevelOrderIterator.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: LevelOrderIterator.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_NestedSet_LevelOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_NestedSet_LevelOrderIterator
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/NestedSet/PostOrderIterator.php b/lib/Doctrine/TODO/Node/NestedSet/PostOrderIterator.php
new file mode 100644
index 000000000..833bb83e7
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/NestedSet/PostOrderIterator.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: PostOrderIterator.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_NestedSet_PostOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_NestedSet_PostOrderIterator
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Node/NestedSet/PreOrderIterator.php b/lib/Doctrine/TODO/Node/NestedSet/PreOrderIterator.php
new file mode 100644
index 000000000..4d61b1835
--- /dev/null
+++ b/lib/Doctrine/TODO/Node/NestedSet/PreOrderIterator.php
@@ -0,0 +1,183 @@
+<?php
+/*
+ *  $Id: PreOrderIterator.php 4364 2008-05-13 21:20:34Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Node_NestedSet_PreOrderIterator
+ *
+ * @package     Doctrine
+ * @subpackage  Node
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 4364 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Node_NestedSet_PreOrderIterator implements Iterator
+{
+    /**
+     * @var Doctrine_Collection $collection
+     */
+    protected $collection;
+
+    /**
+     * @var array $keys
+     */
+    protected $keys;
+
+    /**
+     * @var mixed $key
+     */
+    protected $key;
+
+    /**
+     * @var integer $index
+     */
+    protected $index;
+
+    /**
+     * @var integer $index
+     */
+    protected $prevIndex;
+
+    /**
+     * @var integer $index
+     */
+    protected $traverseLevel;
+
+    /**
+     * @var integer $count
+     */
+    protected $count;
+
+    public function __construct($record, $opts)
+    {
+        $componentName = $record->getTable()->getComponentName();
+
+        $q = $record->getTable()->createQuery();
+
+        $params = array($record->get('lft'), $record->get('rgt'));
+        if (isset($opts['include_record']) && $opts['include_record']) {
+            $query = $q->where("$componentName.lft >= ? AND $componentName.rgt <= ?", $params)->orderBy("$componentName.lft asc");
+        } else {
+            $query = $q->where("$componentName.lft > ? AND $componentName.rgt < ?", $params)->orderBy("$componentName.lft asc");
+        }
+        
+        $query = $record->getTable()->getTree()->returnQueryWithRootId($query, $record->getNode()->getRootValue());
+
+        $this->maxLevel   = isset($opts['depth']) ? ($opts['depth'] + $record->getNode()->getLevel()) : 0;
+        $this->options    = $opts;
+        $this->collection = isset($opts['collection']) ? $opts['collection'] : $query->execute();
+        $this->keys       = $this->collection->getKeys();
+        $this->count      = $this->collection->count();
+        $this->index      = -1;
+        $this->level      = $record->getNode()->getLevel();
+        $this->prevLeft   = $record->getNode()->getLeftValue();
+
+        // clear the table identity cache
+        $record->getTable()->clear();
+    }
+
+    /**
+     * rewinds the iterator
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->index = -1;
+        $this->key = null;
+    }
+
+    /**
+     * returns the current key
+     *
+     * @return integer
+     */
+    public function key()
+    {
+        return $this->key;
+    }
+
+    /**
+     * returns the current record
+     *
+     * @return Doctrine_Entity
+     */
+    public function current()
+    {
+        $record = $this->collection->get($this->key);
+        $record->getNode()->setLevel($this->level);
+        return $record;
+    }
+
+    /**
+     * advances the internal pointer
+     *
+     * @return void
+     */
+    public function next()
+    {
+        while ($current = $this->advanceIndex()) {
+            if ($this->maxLevel && ($this->level > $this->maxLevel)) {
+                continue;
+            }
+
+            return $current;
+        }
+
+        return false;
+    }
+
+    /**
+     * @return boolean                          whether or not the iteration will continue
+     */
+    public function valid()
+    {
+        return ($this->index < $this->count);
+    }
+
+    public function count()
+    {
+        return $this->count;
+    }
+
+    private function updateLevel()
+    {
+        if ( ! (isset($this->options['include_record']) && $this->options['include_record'] && $this->index == 0)) {
+            $left = $this->collection->get($this->key)->getNode()->getLeftValue();
+            $this->level += $this->prevLeft - $left + 2;
+            $this->prevLeft = $left;
+        }
+    }
+
+    private function advanceIndex()
+    {
+        $this->index++;
+        $i = $this->index;
+        if (isset($this->keys[$i])) {
+            $this->key   = $this->keys[$i];
+            $this->updateLevel();
+            return $this->current();
+        }
+
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Pager/Exception.php b/lib/Doctrine/TODO/Pager/Exception.php
new file mode 100644
index 000000000..0cbc25de9
--- /dev/null
+++ b/lib/Doctrine/TODO/Pager/Exception.php
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+Doctrine::autoload('Doctrine_Exception');
+
+/**
+ * Doctrine_Pager_Exception
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+class Doctrine_Pager_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Pager/Layout.php b/lib/Doctrine/TODO/Pager/Layout.php
new file mode 100644
index 000000000..1eb6851a4
--- /dev/null
+++ b/lib/Doctrine/TODO/Pager/Layout.php
@@ -0,0 +1,516 @@
+<?php
+
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+Doctrine::autoload('Doctrine_Pager_Range');
+
+/**
+ * Doctrine_Pager_Layout
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+class Doctrine_Pager_Layout
+{
+    /**
+     * @var Doctrine_Pager $_pager      Doctrine_Pager object related to the pager layout
+     */
+    private $_pager;
+
+    /**
+     * @var Doctrine_Pager_Range $_pagerRange      Doctrine_Pager_Range object related to the pager layout
+     */
+    private $_pagerRange;
+
+    /**
+     * @var string $_template      Template to be applied for inactive pages
+     *                             (and also active is selected template is not defined)
+     */
+    private $_template;
+
+    /**
+     * @var string $_selectedTemplate     Template to be applied for active page
+     */
+    private $_selectedTemplate;
+
+    /**
+     * @var string $_separatorTemplate     Separator template, applied between each page
+     */
+    private $_separatorTemplate;
+
+    /**
+     * @var string $_urlMask      URL to be assigned for each page. Masks are used as: {%var_name}
+     */
+    private $_urlMask;
+    
+    /**
+     * @var array $_maskReplacements      Stores references of masks and their correspondent 
+     *                                    (replaces defined masks with new masks or values)
+     */
+    private $_maskReplacements = array();
+
+
+    /**
+     * __construct
+     *
+     * @param Doctrine_Pager $pager     Doctrine_Pager object related to the pager layout
+     * @param Doctrine_Pager_Range $pagerRange     Doctrine_Pager_Range object related to the pager layout
+     * @param string $urlMask     URL to be assigned for each page
+     * @return void
+     */
+    public function __construct($pager, $pagerRange, $urlMask)
+    {
+        $this->_setPager($pager);
+        $this->_setPagerRange($pagerRange);
+        $this->_setUrlMask($urlMask);
+
+        $this->setTemplate('[<a href="{%url}">{%page}</a>]');
+        $this->setSelectedTemplate('');
+        $this->setSeparatorTemplate('');
+    }
+
+
+    /**
+     * getPager
+     *
+     * Returns the Doctrine_Pager object related to the pager layout
+     *
+     * @return Doctrine_Pager        Doctrine_Pager object related to the pager range
+     */
+    public function getPager()
+    {
+        return $this->_pager;
+    }
+
+
+    /**
+     * _setPager
+     *
+     * Defines the Doctrine_Pager object related to the pager layout
+     *
+     * @param $pager       Doctrine_Pager object related to the pager range
+     * @return void
+     */
+    protected function _setPager($pager)
+    {
+        $this->_pager = $pager;
+    }
+
+
+    /**
+     * execute
+     *
+     * Handy method to execute the query without need to retrieve the Pager instance
+     *
+     * @param $params               Optional parameters to Doctrine_Query::execute
+     * @param $hydrationMode        Hydration Mode of Doctrine_Query::execute 
+     *                              returned ResultSet. Doctrine::Default is FETCH_RECORD
+     * @return Doctrine_Collection  The root collection
+     */
+    public function execute($params = array(), $hydrationMode = Doctrine::FETCH_RECORD)
+    {
+        return $this->getPager()->execute($params, $hydrationMode);
+    }
+
+
+    /**
+     * getPagerRange
+     *
+     * Returns the Doctrine_Pager_Range subclass object related to the pager layout
+     *
+     * @return Doctrine_Pager_Range        Doctrine_Pager_Range subclass object related to the pager range
+     */
+    public function getPagerRange()
+    {
+        return $this->_pagerRange;
+    }
+
+
+    /**
+     * _setPagerRange
+     *
+     * Defines the Doctrine_Pager_Range subclass object related to the pager layout
+     *
+     * @param $pagerRange       Doctrine_Pager_Range subclass object related to the pager range
+     * @return void
+     */
+    protected function _setPagerRange($pagerRange)
+    {
+        $this->_pagerRange = $pagerRange;
+        $this->getPagerRange()->setPager($this->getPager());
+    }
+
+
+    /**
+     * getUrlMask
+     *
+     * Returns the URL to be assigned for each page
+     *
+     * @return string        URL to be assigned for each page
+     */
+    public function getUrlMask()
+    {
+        return $this->_urlMask;
+    }
+
+
+    /**
+     * _setUrlMask
+     *
+     * Defines the URL to be assigned for each page
+     *
+     * @param $urlMask       URL to be assigned for each page
+     * @return void
+     */
+    protected function _setUrlMask($urlMask)
+    {
+        $this->_urlMask = $urlMask;
+    }
+
+
+     /**
+     * getTemplate
+     *
+     * Returns the Template to be applied for inactive pages
+     *
+     * @return string        Template to be applied for inactive pages
+     */
+    public function getTemplate()
+    {
+        return $this->_template;
+    }
+
+
+    /**
+     * setTemplate
+     *
+     * Defines the Template to be applied for inactive pages 
+     * (also active page if selected template not defined)
+     *
+     * @param $template       Template to be applied for inactive pages
+     * @return void
+     */
+    public function setTemplate($template)
+    {
+        $this->_template = $template;
+    }
+
+
+    /**
+     * getSelectedTemplate
+     *
+     * Returns the Template to be applied for active page
+     *
+     * @return string        Template to be applied for active page
+     */
+    public function getSelectedTemplate()
+    {
+        return $this->_selectedTemplate;
+    }
+
+
+    /**
+     * setSelectedTemplate
+     *
+     * Defines the Template to be applied for active page
+     *
+     * @param $selectedTemplate       Template to be applied for active page
+     * @return void
+     */
+    public function setSelectedTemplate($selectedTemplate)
+    {
+        $this->_selectedTemplate = $selectedTemplate;
+    }
+
+
+    /**
+     * getSeparatorTemplate
+     *
+     * Returns the Separator template, applied between each page
+     *
+     * @return string        Separator template, applied between each page
+     */
+    public function getSeparatorTemplate()
+    {
+        return $this->_separatorTemplate;
+    }
+
+
+    /**
+     * setSeparatorTemplate
+     *
+     * Defines the Separator template, applied between each page
+     *
+     * @param $separatorTemplate       Separator template, applied between each page
+     * @return void
+     */ 
+    public function setSeparatorTemplate($separatorTemplate)
+    {
+        $this->_separatorTemplate = $separatorTemplate;
+    }
+
+
+    /**
+     * addMaskReplacement
+     *
+     * Defines a mask replacement. When parsing template, it converts replacement
+     * masks into new ones (or values), allowing to change masks behavior on the fly
+     *
+     * @param $oldMask       Mask to be replaced
+     * @param $newMask       Mask or Value that will be defined after replacement
+     * @param $asValue       Optional value (default false) that if defined as true,
+     *                       changes the bahavior of replacement mask to replacement
+     *                       value
+     * @return void
+     */ 
+    public function addMaskReplacement($oldMask, $newMask, $asValue = false)
+    {
+        if (($oldMask = trim($oldMask)) != 'page_number') {
+            $this->_maskReplacements[$oldMask] = array(
+                'newMask' => $newMask,
+                'asValue' => ($asValue === false) ? false : true
+            );
+        }
+    }
+
+
+    /**
+     * removeMaskReplacement
+     *
+     * Remove a mask replacement
+     *
+     * @param $oldMask       Replacement Mask to be removed
+     * @return void
+     */ 
+    public function removeMaskReplacement($oldMask)
+    {
+        if (isset($this->_maskReplacements[$oldMask])) {
+            $this->_maskReplacements[$oldMask] = null;
+            unset($this->_maskReplacements[$oldMask]);
+        }
+    }
+    
+    
+    /**
+     * cleanMaskReplacements
+     *
+     * Remove all mask replacements
+     *
+     * @return void
+     */ 
+    public function cleanMaskReplacements()
+    {
+        $this->_maskReplacements = null;
+        $this->_maskReplacements = array();
+    }
+
+
+    /**
+     * display
+     *
+     * Displays the pager on screen based on templates and options defined
+     *
+     * @param $options    Optional parameters to be applied in template and url mask
+     * @param $return     Optional parameter if you want to capture the output of this method call 
+     *                    (Default value is false), instead of printing it
+     * @return mixed      If you would like to capture the output of Doctrine_Pager_Layout::display(),
+     *                    use the return  parameter. If this parameter is set to TRUE, this method 
+     *                    will return its output, instead of printing it (which it does by default)
+     */
+    public function display($options = array(), $return = false)
+    {
+        $range = $this->getPagerRange()->rangeAroundPage();
+        $str = '';
+
+        // For each page in range
+        for ($i = 0, $l = count($range); $i < $l; $i++) {
+            // Define some optional mask values
+            $options['page_number'] = $range[$i];
+
+            $str .= $this->processPage($options);
+
+            // Apply separator between pages
+            if ($i < $l - 1) {
+                $str .= $this->getSeparatorTemplate();
+            }
+        }
+
+        // Possible wish to return value instead of print it on screen
+        if ($return) {
+            return $str;
+        }
+
+        echo $str;
+    }
+
+
+    /**
+     * processPage
+     *
+     * Parses the template and returns the string of a processed page
+     *
+     * @param array    Optional parameters to be applied in template and url mask
+     * @return string  Processed template for the given page
+     */
+    public function processPage($options = array())
+    {
+        // Check if at least basic options are defined
+        if (!isset($options['page_number'])) {
+            throw new Doctrine_Pager_Exception(
+                'Cannot process template of the given page. ' .
+                'Missing at least one of needed parameters: \'page\' or \'page_number\''
+            );
+
+            // Should never reach here
+            return '';
+        }
+
+        // Assign "page" options index if not defined yet
+        if (!isset($this->_maskReplacements['page']) && !isset($options['page'])) {
+            $options['page'] = $options['page_number'];
+        }
+
+        return $this->_parseTemplate($options);
+    }
+
+
+    /**
+     * Simply calls display, and returns the output.
+     */
+    public function __toString()
+    {
+      return $this->display(array(), true);
+    }
+
+
+    /**
+     * _parseTemplate
+     *
+     * Parse the template of a given page and return the processed template
+     *
+     * @param array    Optional parameters to be applied in template and url mask
+     * @return string  
+     */
+    protected function _parseTemplate($options = array())
+    {
+        $str = $this->_parseUrlTemplate($options);
+        $replacements = $this->_parseReplacementsTemplate($options);
+
+        return strtr($str, $replacements);
+    }
+
+
+    /**
+     * _parseUrlTemplate
+     *
+     * Parse the url mask to return the correct template depending of the options sent.
+     * Already process the mask replacements assigned.
+     *
+     * @param $options    Optional parameters to be applied in template and url mask
+     * @return string
+     */
+    protected function _parseUrlTemplate($options = array())
+    {
+        $str = '';
+
+        // If given page is the current active one
+        if ($options['page_number'] == $this->getPager()->getPage()) {
+            $str = $this->_parseMaskReplacements($this->getSelectedTemplate());
+        }
+
+        // Possible attempt where Selected == Template
+        if ($str == '') {
+            $str = $this->_parseMaskReplacements($this->getTemplate());
+        }
+
+        return $str;
+    }
+
+
+    /**
+     * _parseUrl
+     *
+     * Parse the mask replacements of a given page
+     *
+     * @param $options    Optional parameters to be applied in template and url mask
+     * @return string
+     */
+    protected function _parseReplacementsTemplate($options = array())
+    {
+        // Defining "url" options index to allow {%url} mask
+        $options['url'] = $this->_parseUrl($options);
+
+        $replacements = array();
+
+        foreach ($options as $k => $v) {
+            $replacements['{%'.$k.'}'] = $v;
+        }
+
+        return $replacements;
+    }
+
+
+    /**
+     * _parseUrl
+     *
+     * Parse the url mask of a given page and return the processed url
+     *
+     * @param $options    Optional parameters to be applied in template and url mask
+     * @return string
+     */
+    protected function _parseUrl($options = array())
+    {
+        $str = $this->_parseMaskReplacements($this->getUrlMask());
+
+        $replacements = array();
+
+        foreach ($options as $k => $v) {
+            $replacements['{%'.$k.'}'] = $v;
+        }
+
+        return strtr($str, $replacements);
+    }
+
+
+    /**
+     * _parseMaskReplacements
+     *
+     * Parse the mask replacements, changing from to-be replaced mask with new masks/values
+     *
+     * @param $str    String to have masks replaced
+     * @return string  
+     */
+    protected function _parseMaskReplacements($str)
+    {
+        $replacements = array();
+
+        foreach ($this->_maskReplacements as $k => $v) {
+            $replacements['{%'.$k.'}'] = ($v['asValue'] === true) ? $v['newMask'] : '{%'.$v['newMask'].'}';
+        }
+
+        return strtr($str, $replacements);
+    }
+}
diff --git a/lib/Doctrine/TODO/Pager/Range.php b/lib/Doctrine/TODO/Pager/Range.php
new file mode 100644
index 000000000..396cebfb1
--- /dev/null
+++ b/lib/Doctrine/TODO/Pager/Range.php
@@ -0,0 +1,176 @@
+<?php
+
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Pager_Range
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+abstract class Doctrine_Pager_Range
+{
+    /**
+     * @var array $_options     Custom Doctrine_Pager_Range implementation options
+     */
+    protected $_options;
+
+    /**
+     * @var Doctrine_Pager $pager     Doctrine_Pager object related to the pager range
+     */
+    private $pager;
+
+
+    /**
+     * __construct
+     *
+     * @param array $options     Custom subclass implementation options.
+     *                           Default is a blank array
+     * @param Doctrine_Pager $pager     Optional Doctrine_Pager object to be associated
+     * @return void
+     */
+    final public function __construct($options = array(), $pager = null)
+    {
+        $this->_setOptions($options);
+
+        if ($pager !== null) {
+            $this->setPager($pager);
+        }
+    }
+
+
+    /**
+     * getPager
+     *
+     * Returns the Doctrine_Pager object related to the pager range
+     *
+     * @return Doctrine_Pager        Doctrine_Pager object related to the pager range
+     */
+    public function getPager()
+    {
+        return $this->pager;
+    }
+
+
+    /**
+     * setPager
+     *
+     * Defines the Doctrine_Pager object related to the pager range and
+     * automatically (re-)initialize Doctrine_Pager_Range
+     *
+     * @param $pager       Doctrine_Pager object related to the pager range
+     * @return void
+     */
+    public function setPager($pager)
+    {
+        $this->pager = $pager;
+
+        // Lazy-load initialization. It only should be called when all
+        // needed information data is ready (this can only happens when we have
+        // options stored and a Doctrine_Pager assocated)
+        $this->_initialize();
+    }
+
+
+    /**
+     * getOptions
+     *
+     * Returns the custom Doctrine_Pager_Range implementation options
+     *
+     * @return array        Custom Doctrine_Pager_Range implementation options
+     */
+    public function getOptions()
+    {
+        return $this->_options;
+    }
+
+
+    /**
+     * getOption
+     *
+     * Returns the custom Doctrine_Pager_Range implementation offset option
+     *
+     * @return array        Custom Doctrine_Pager_Range implementation options
+     */
+    public function getOption($option)
+    {
+        if (isset($this->_options[$option])) {
+            return $this->_options[$option];
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot access unexistent option \'' . $option . '\' in Doctrine_Pager_Range class'
+        );
+    }
+
+
+    /**
+     * _setOptions
+     *
+     * Defines the subclass implementation options
+     *
+     * @param $options       Custom Doctrine_Pager_Range implementation options
+     * @return void
+     */
+    protected function _setOptions($options)
+    {
+        $this->_options = $options;
+    }
+
+
+    /**
+     * isInRange
+     *
+     * Check if a given page is in the range
+     *
+     * @param $page       Page to be checked
+     * @return boolean
+     */
+    public function isInRange($page)
+    {
+        return (array_search($page, $this->rangeAroundPage()) !== false);
+    }
+
+
+    /**
+     * _initialize
+     *
+     * Initialize Doctrine_Page_Range subclass which does custom class definitions
+     *
+     * @return void
+     */
+    abstract protected function _initialize();
+
+
+    /**
+     * rangeAroundPage
+     *
+     * Calculate and returns an array representing the range around the current page
+     *
+     * @return array
+     */
+    abstract public function rangeAroundPage();
+}
diff --git a/lib/Doctrine/TODO/Pager/Range/Jumping.php b/lib/Doctrine/TODO/Pager/Range/Jumping.php
new file mode 100644
index 000000000..1c238a724
--- /dev/null
+++ b/lib/Doctrine/TODO/Pager/Range/Jumping.php
@@ -0,0 +1,120 @@
+<?php
+
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+Doctrine::autoload('Doctrine_Pager_Range');
+
+/**
+ * Doctrine_Pager_Range_Jumping
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+class Doctrine_Pager_Range_Jumping extends Doctrine_Pager_Range
+{
+    /**
+     * @var int $_chunkLength     Chunk length to be returned
+     */
+    private $_chunkLength;
+
+
+    /**
+     * _initialize
+     *
+     * Initialize Doctrine_Pager_Range_Jumping and does custom assignments
+     *
+     * @return void
+     */
+    protected function _initialize()
+    {
+        if (isset($this->_options['chunk'])) {
+            $this->_setChunkLength($this->_options['chunk']);
+        } else {
+            throw new Doctrine_Pager_Exception('Missing parameter \'chunk\' that must be define in options.');
+        }
+    }
+
+
+    /**
+     * getChunkLength
+     *
+     * Returns the size of the chunk defined
+     *
+     * @return int        Chunk length
+     */
+    public function getChunkLength()
+    {
+        return $this->_chunkLength;
+    }
+
+
+    /**
+     * _setChunkLength
+     *
+     * Defines the size of the chunk
+     *
+     * @param $chunkLength       Chunk length
+     * @return void
+     */
+    protected function _setChunkLength($chunkLength)
+    {
+        $this->_chunkLength = $chunkLength;
+    }
+
+
+    /**
+     * rangeAroundPage
+     *
+     * Calculate and returns an array representing the range around the current page
+     *
+     * @return array
+     */
+    public function rangeAroundPage()
+    {
+        $pager = $this->getPager();
+
+        if ($pager->getExecuted()) {
+            $page = $pager->getPage();
+
+            // Define initial assignments for StartPage and EndPage
+            $startPage = $page - ($page - 1) % $this->getChunkLength();
+            $endPage = ($startPage + $this->getChunkLength()) - 1;
+
+            // Check for EndPage out-range
+            if ($endPage > $pager->getLastPage()) {
+                $endPage = $pager->getLastPage();
+            }
+
+            // No need to check for out-range in start, it will never happens
+
+            return range($startPage, $endPage);
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot retrieve the range around the page of a not yet executed Pager query'
+        );
+    }
+}
diff --git a/lib/Doctrine/TODO/Pager/Range/Sliding.php b/lib/Doctrine/TODO/Pager/Range/Sliding.php
new file mode 100644
index 000000000..92b84a405
--- /dev/null
+++ b/lib/Doctrine/TODO/Pager/Range/Sliding.php
@@ -0,0 +1,136 @@
+<?php
+
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+Doctrine::autoload('Doctrine_Pager_Range');
+
+/**
+ * Doctrine_Pager_Range_Sliding
+ *
+ * @author      Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @package     Doctrine
+ * @subpackage  Pager
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       0.9
+ */
+class Doctrine_Pager_Range_Sliding extends Doctrine_Pager_Range
+{
+    /**
+     * @var int $_chunkLength     Chunk length to be returned
+     */
+    private $_chunkLength;
+
+
+    /**
+     * _initialize
+     *
+     * Initialize Doctrine_Pager_Range_Sliding and does custom assignments
+     *
+     * @return void
+     */
+    protected function _initialize()
+    {
+        if (isset($this->_options['chunk'])) {
+            $this->_setChunkLength($this->_options['chunk']);
+        } else {
+            throw new Doctrine_Pager_Exception('Missing parameter \'chunk\' that must be defined in options.');
+        }
+    }
+
+
+    /**
+     * getChunkLength
+     *
+     * Returns the size of the chunk defined
+     *
+     * @return int        Chunk length
+     */
+    public function getChunkLength()
+    {
+        return $this->_chunkLength;
+    }
+
+
+    /**
+     * _setChunkLength
+     *
+     * Defines the size of the chunk
+     *
+     * @param $chunkLength       Chunk length
+     * @return void
+     */
+    protected function _setChunkLength($chunkLength)
+    {
+        $chunkLength = (int) $chunkLength;
+        if (!$chunkLength) {
+            $chunkLength = 1;
+        } else {
+            $this->_chunkLength = $chunkLength;
+        }
+    }
+
+
+    /**
+     * rangeAroundPage
+     *
+     * Calculate and returns an array representing the range around the current page
+     *
+     * @return array
+     */
+    public function rangeAroundPage()
+    {
+        $pager = $this->getPager();
+
+        if ($pager->getExecuted()) {
+            $page  = $pager->getPage();
+            $pages = $pager->getLastPage();
+
+            $chunk = $this->getChunkLength();
+
+            if ($chunk > $pages) {
+                $chunk = $pages;
+            }
+
+            $chunkStart = $page - (floor($chunk / 2));
+            $chunkEnd   = $page + (ceil($chunk / 2)-1);
+
+            if ($chunkStart < 1) {
+                $adjust = 1 - $chunkStart;
+                $chunkStart = 1;
+                $chunkEnd = $chunkEnd + $adjust;
+            }
+
+            if ($chunkEnd > $pages) {
+                $adjust = $chunkEnd - $pages;
+                $chunkStart = $chunkStart - $adjust;
+                $chunkEnd = $pages;
+            }
+
+            return range($chunkStart, $chunkEnd);
+        }
+
+        throw new Doctrine_Pager_Exception(
+            'Cannot retrieve the range around the page of a not yet executed Pager query'
+        );
+    }
+}
diff --git a/lib/Doctrine/TODO/Parser/Exception.php b/lib/Doctrine/TODO/Parser/Exception.php
new file mode 100644
index 000000000..64a1301c8
--- /dev/null
+++ b/lib/Doctrine/TODO/Parser/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+Doctrine::autoload('Doctrine_Exception');
+/**
+ * Doctrine_Parser_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Parser_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Parser/Json.php b/lib/Doctrine/TODO/Parser/Json.php
new file mode 100644
index 000000000..b05bb28b4
--- /dev/null
+++ b/lib/Doctrine/TODO/Parser/Json.php
@@ -0,0 +1,68 @@
+<?php
+/*
+ *  $Id: Json.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser_Json
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Parser_Json extends Doctrine_Parser
+{
+    /**
+     * dumpData
+     *
+     * Dump an array of data to a specified path or return
+     * 
+     * @param string $array Array of data to dump to json
+     * @param string $path  Path to dump json data to
+     * @return string $json
+     * @return void
+     */
+    public function dumpData($array, $path = null)
+    {
+        $data = json_encode($array);
+        
+        return $this->doDump($data, $path);
+    }
+
+    /**
+     * loadData
+     *
+     * Load and unserialize data from a file or from passed data
+     * 
+     * @param  string $path   Path to dump data to
+     * @return array  $json   Array of json objects
+     */
+    public function loadData($path)
+    {
+        $contents = $this->doLoad($path);
+        
+        $json = json_decode($contents);
+        
+        return $json;
+    }
+}
diff --git a/lib/Doctrine/TODO/Parser/Serialize.php b/lib/Doctrine/TODO/Parser/Serialize.php
new file mode 100644
index 000000000..57a40964e
--- /dev/null
+++ b/lib/Doctrine/TODO/Parser/Serialize.php
@@ -0,0 +1,65 @@
+<?php
+/*
+ *  $Id: Serialize.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser_Serialize
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Parser_Serialize extends Doctrine_Parser
+{
+    /**
+     * dumpData
+     *
+     * Dump an array of data to a specified path or return
+     * 
+     * @param string $array 
+     * @param string $path 
+     * @return void
+     */
+    public function dumpData($array, $path = null)
+    {
+        $data = serialize($array);
+        
+        return $this->doDump($data, $path);
+    }
+
+    /**
+     * loadData
+     *
+     * Load and unserialize data from a file or from passed data
+     * 
+     * @param string $path 
+     * @return void
+     */
+    public function loadData($path)
+    {
+        $contents = $this->doLoad($path);
+        
+        return unserialize($contents);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Parser/Xml.php b/lib/Doctrine/TODO/Parser/Xml.php
new file mode 100644
index 000000000..397086a8b
--- /dev/null
+++ b/lib/Doctrine/TODO/Parser/Xml.php
@@ -0,0 +1,140 @@
+<?php
+/*
+ *  $Id: Xml.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser_Xml
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Parser_Xml extends Doctrine_Parser
+{
+    /**
+     * dumpData
+     * 
+     * Convert array to xml and dump to specified path or return the xml
+     *
+     * @param  string $array Array of data to convert to xml
+     * @param  string $path  Path to write xml data to
+     * @return string $xml
+     * @return void
+     */
+    public function dumpData($array, $path = null)
+    {
+        $data = $this->arrayToXml($array);
+        
+        return $this->doDump($data, $path);
+    }
+
+    /**
+     * arrayToXml
+     *
+     * @param  string $array        Array to convert to xml    
+     * @param  string $rootNodeName Name of the root node
+     * @param  string $xml          SimpleXmlElement
+     * @return string $asXml        String of xml built from array
+     */
+    public function arrayToXml($array, $rootNodeName = 'data', $xml = null)
+    {
+        if ($xml === null) {
+            $xml = new SimpleXmlElement("<?xml version=\"1.0\" encoding=\"utf-8\"?><$rootNodeName/>");
+        }
+
+        foreach($array as $key => $value)
+        {
+            if (is_array($value)) {
+                $node = $xml->addChild($key);
+
+                $this->arrayToXml($value, $rootNodeName, $node);
+            } else {
+                $value = htmlentities($value);
+
+                $xml->addChild($key, $value);
+            }
+        }
+      
+      return $xml->asXML();
+    }
+
+    /**
+     * loadData
+     *
+     * Load xml file and return array of data
+     *
+     * @param  string $path  Path to load xml data from
+     * @return array  $array Array of data converted from xml
+     */
+    public function loadData($path)
+    {
+        $contents = $this->doLoad($path);
+        
+        $simpleXml = simplexml_load_string($contents);
+        
+        return $this->prepareData($simpleXml);
+    }
+
+    /**
+     * prepareData
+     *
+     * Prepare simple xml to array for return
+     *
+     * @param  string $simpleXml 
+     * @return array  $return
+     */
+    public function prepareData($simpleXml)
+    {
+        if ($simpleXml instanceof SimpleXMLElement) {
+            $children = $simpleXml->children();
+            $return = null;
+        }
+
+        foreach ($children as $element => $value) {
+            if ($value instanceof SimpleXMLElement) {
+                $values = (array) $value->children();
+
+                if (count($values) > 0) {
+                    $return[$element] = $this->prepareData($value);
+                } else {
+                    if ( ! isset($return[$element])) {
+                        $return[$element] = (string) $value;
+                    } else {
+                        if ( ! is_array($return[$element])) {
+                            $return[$element] = array($return[$element], (string) $value);
+                        } else {
+                            $return[$element][] = (string) $value;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (is_array($return)) {
+            return $return;
+        } else {
+            return array();
+        }
+    }
+}
diff --git a/lib/Doctrine/TODO/Parser/Yml.php b/lib/Doctrine/TODO/Parser/Yml.php
new file mode 100644
index 000000000..fae25e1d2
--- /dev/null
+++ b/lib/Doctrine/TODO/Parser/Yml.php
@@ -0,0 +1,74 @@
+<?php
+require_once('spyc.php');
+
+/*
+ *  $Id: Yml.php 1080 2007-02-10 18:17:08Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Parser_Yml
+ *
+ * @package     Doctrine
+ * @subpackage  Parser
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Parser_Yml extends Doctrine_Parser
+{
+    /**
+     * dumpData
+     *
+     * Dump an array of data to a specified path or return
+     * 
+     * @param  string $array Array of data to dump to yaml
+     * @param  string $path  Path to dump the yaml to
+     * @return string $yaml
+     * @return void
+     */
+    public function dumpData($array, $path = null)
+    {
+        $spyc = new Doctrine_Spyc();
+        
+        $data = $spyc->dump($array, false, false);
+        
+        return $this->doDump($data, $path);
+    }
+
+    /**
+     * loadData
+     *
+     * Load and parse data from a yml file
+     * 
+     * @param  string  $path  Path to load yaml data from
+     * @return array   $array Array of parsed yaml data
+     */
+    public function loadData($path)
+    {
+        $contents = $this->doLoad($path);
+
+        $spyc = new Doctrine_Spyc();
+        
+        $array = $spyc->load($contents);
+        
+        return $array;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Parser/spyc.php b/lib/Doctrine/TODO/Parser/spyc.php
new file mode 100644
index 000000000..6d146657c
--- /dev/null
+++ b/lib/Doctrine/TODO/Parser/spyc.php
@@ -0,0 +1,881 @@
+<?php
+  /**
+   * Spyc -- A Simple PHP YAML Class
+   * @version 0.2.(5) -- 2006-12-31
+   * @author Chris Wanstrath <chris@ozmm.org>
+   * @author Vlad Andersen <vlad@oneiros.ru>
+   * @link http://spyc.sourceforge.net/
+   * @copyright Copyright 2005-2006 Chris Wanstrath
+   * @license http://www.opensource.org/licenses/mit-license.php MIT License
+   * @package Doctrine
+   * @subpackage Spyc
+   */
+
+  /**
+   * A node, used by Doctrine_Spyc for parsing YAML.
+   * @package Doctrine
+   * @subpackage Spyc
+   */
+  class Doctrine_YamlNode {
+    /**#@+
+     * @access public
+     * @var string
+     */
+    var $parent;
+    var $id;
+
+    /**#@+*/
+    /**
+     * @access public
+     * @var mixed
+     */
+    var $data;
+
+    /**
+     * @access public
+     * @var int
+     */
+    var $indent;
+
+    /**
+     * @access public
+     * @var bool
+     */
+    var $children = false;
+
+    /**
+     * The constructor assigns the node a unique ID.
+     * @access public
+     * @return void
+     */
+    function Doctrine_YamlNode($nodeId) {
+      $this->id = $nodeId;
+    }
+  }
+
+  /**
+   * The Simple PHP YAML Class.
+   *
+   * This class can be used to read a YAML file and convert its contents
+   * into a PHP array.  It currently supports a very limited subsection of
+   * the YAML spec.
+   *
+   * Usage:
+   * <code>
+   *   $parser = new Doctrine_Spyc;
+   *   $array  = $parser->load($file);
+   * </code>
+   * @package Doctrine
+   * @subpackage Spyc
+   */
+  class Doctrine_Spyc {
+
+    /**
+     * Load YAML into a PHP array statically
+     *
+     * The load method, when supplied with a YAML stream (string or file),
+     * will do its best to convert YAML in a file into a PHP array.  Pretty
+     * simple.
+     *  Usage:
+     *  <code>
+     *   $array = Doctrine_Spyc::YAMLLoad('lucky.yaml');
+     *   print_r($array);
+     *  </code>
+     * @access public
+     * @return array
+     * @param string $input Path of YAML file or string containing YAML
+     */
+    function YAMLLoad($input) {
+      $spyc = new Doctrine_Spyc;
+      return $spyc->load($input);
+    }
+
+    /**
+     * Dump YAML from PHP array statically
+     *
+     * The dump method, when supplied with an array, will do its best
+     * to convert the array into friendly YAML.  Pretty simple.  Feel free to
+     * save the returned string as nothing.yaml and pass it around.
+     *
+     * Oh, and you can decide how big the indent is and what the wordwrap
+     * for folding is.  Pretty cool -- just pass in 'false' for either if
+     * you want to use the default.
+     *
+     * Indent's default is 2 spaces, wordwrap's default is 40 characters.  And
+     * you can turn off wordwrap by passing in 0.
+     *
+     * @access public
+     * @return string
+     * @param array $array PHP array
+     * @param int $indent Pass in false to use the default, which is 2
+     * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
+     */
+    function YAMLDump($array,$indent = false,$wordwrap = false) {
+      $spyc = new Doctrine_Spyc;
+      return $spyc->dump($array,$indent,$wordwrap);
+    }
+
+    /**
+     * Load YAML into a PHP array from an instantiated object
+     *
+     * The load method, when supplied with a YAML stream (string or file path),
+     * will do its best to convert the YAML into a PHP array.  Pretty simple.
+     *  Usage:
+     *  <code>
+     *   $parser = new Doctrine_Spyc;
+     *   $array  = $parser->load('lucky.yaml');
+     *   print_r($array);
+     *  </code>
+     * @access public
+     * @return array
+     * @param string $input Path of YAML file or string containing YAML
+     */
+    function load($input) {
+      // See what type of input we're talking about
+      // If it's not a file, assume it's a string
+      if ( ! empty($input) && (strpos($input, "\n") === false)
+          && file_exists($input)) {
+        $yaml = file($input);
+      } else {
+        $yaml = explode("\n",$input);
+      }
+      // Initiate some objects and values
+      $base              = new Doctrine_YamlNode (1);
+      $base->indent      = 0;
+      $this->_lastIndent = 0;
+      $this->_lastNode   = $base->id;
+      $this->_inBlock    = false;
+      $this->_isInline   = false;
+      $this->_nodeId     = 2;
+
+      foreach ($yaml as $linenum => $line) {
+        $ifchk = trim($line);
+
+        // If the line starts with a tab (instead of a space), throw a fit.
+        if (preg_match('/^(\t)+(\w+)/', $line)) {
+          $err = 'ERROR: Line '. ($linenum + 1) .' in your input YAML begins'.
+                 ' with a tab.  YAML only recognizes spaces.  Please reformat.';
+          die($err);
+        }
+
+        if ($this->_inBlock === false && empty($ifchk)) {
+          continue;
+        } elseif ($this->_inBlock == true && empty($ifchk)) {
+          $last =& $this->_allNodes[$this->_lastNode];
+          $last->data[key($last->data)] .= "\n";
+        } elseif ($ifchk{0} != '#' && substr($ifchk,0,3) != '---') {
+          // Create a new node and get its indent
+          $node         = new Doctrine_YamlNode ($this->_nodeId);
+		  $this->_nodeId++;
+
+          $node->indent = $this->_getIndent($line);
+
+          // Check where the node lies in the hierarchy
+          if ($this->_lastIndent == $node->indent) {
+            // If we're in a block, add the text to the parent's data
+            if ($this->_inBlock === true) {
+              $parent =& $this->_allNodes[$this->_lastNode];
+              $parent->data[key($parent->data)] .= trim($line).$this->_blockEnd;
+            } else {
+              // The current node's parent is the same as the previous node's
+              if (isset($this->_allNodes[$this->_lastNode])) {
+                $node->parent = $this->_allNodes[$this->_lastNode]->parent;
+              }
+            }
+          } elseif ($this->_lastIndent < $node->indent) {
+            if ($this->_inBlock === true) {
+              $parent =& $this->_allNodes[$this->_lastNode];
+              $parent->data[key($parent->data)] .= trim($line).$this->_blockEnd;
+            } elseif ($this->_inBlock === false) {
+              // The current node's parent is the previous node
+              $node->parent = $this->_lastNode;
+
+              // If the value of the last node's data was > or | we need to
+              // start blocking i.e. taking in all lines as a text value until
+              // we drop our indent.
+              $parent =& $this->_allNodes[$node->parent];
+              $this->_allNodes[$node->parent]->children = true;
+              if (is_array($parent->data)) {
+                $chk = '';
+                if (isset ($parent->data[key($parent->data)]))
+                    $chk = $parent->data[key($parent->data)];
+                if ($chk === '>') {
+                  $this->_inBlock  = true;
+                  $this->_blockEnd = ' ';
+                  $parent->data[key($parent->data)] =
+                        str_replace('>','',$parent->data[key($parent->data)]);
+                  $parent->data[key($parent->data)] .= trim($line).' ';
+                  $this->_allNodes[$node->parent]->children = false;
+                  $this->_lastIndent = $node->indent;
+                } elseif ($chk === '|') {
+                  $this->_inBlock  = true;
+                  $this->_blockEnd = "\n";
+                  $parent->data[key($parent->data)] =
+                        str_replace('|','',$parent->data[key($parent->data)]);
+                  $parent->data[key($parent->data)] .= trim($line)."\n";
+                  $this->_allNodes[$node->parent]->children = false;
+                  $this->_lastIndent = $node->indent;
+                }
+              }
+            }
+          } elseif ($this->_lastIndent > $node->indent) {
+            // Any block we had going is dead now
+            if ($this->_inBlock === true) {
+              $this->_inBlock = false;
+              if ($this->_blockEnd = "\n") {
+                $last =& $this->_allNodes[$this->_lastNode];
+                $last->data[key($last->data)] =
+                      trim($last->data[key($last->data)]);
+              }
+            }
+
+            // We don't know the parent of the node so we have to find it
+            // foreach ($this->_allNodes as $n) {
+            foreach ($this->_indentSort[$node->indent] as $n) {
+              if ($n->indent == $node->indent) {
+                $node->parent = $n->parent;
+              }
+            }
+          }
+
+          if ($this->_inBlock === false) {
+            // Set these properties with information from our current node
+            $this->_lastIndent = $node->indent;
+            // Set the last node
+            $this->_lastNode = $node->id;
+            // Parse the YAML line and return its data
+            $node->data = $this->_parseLine($line);
+            // Add the node to the master list
+            $this->_allNodes[$node->id] = $node;
+            // Add a reference to the parent list
+            $this->_allParent[intval($node->parent)][] = $node->id;
+            // Add a reference to the node in an indent array
+            $this->_indentSort[$node->indent][] =& $this->_allNodes[$node->id];
+            // Add a reference to the node in a References array if this node
+            // has a YAML reference in it.
+            if (
+              ( (is_array($node->data)) &&
+                isset($node->data[key($node->data)]) &&
+                ( ! is_array($node->data[key($node->data)])) )
+              &&
+              ( (preg_match('/^&([^ ]+)/',$node->data[key($node->data)]))
+                ||
+                (preg_match('/^\*([^ ]+)/',$node->data[key($node->data)])) )
+            ) {
+                $this->_haveRefs[] =& $this->_allNodes[$node->id];
+            } elseif (
+              ( (is_array($node->data)) &&
+                isset($node->data[key($node->data)]) &&
+                 (is_array($node->data[key($node->data)])) )
+            ) {
+              // Incomplete reference making code.  Ugly, needs cleaned up.
+              foreach ($node->data[key($node->data)] as $d) {
+                if ( !is_array($d) &&
+                  ( (preg_match('/^&([^ ]+)/',$d))
+                    ||
+                    (preg_match('/^\*([^ ]+)/',$d)) )
+                  ) {
+                    $this->_haveRefs[] =& $this->_allNodes[$node->id];
+                }
+              }
+            }
+          }
+        }
+      }
+      unset($node);
+
+      // Here we travel through node-space and pick out references (& and *)
+      $this->_linkReferences();
+
+      // Build the PHP array out of node-space
+      $trunk = $this->_buildArray();
+      return $trunk;
+    }
+
+    /**
+     * Dump PHP array to YAML
+     *
+     * The dump method, when supplied with an array, will do its best
+     * to convert the array into friendly YAML.  Pretty simple.  Feel free to
+     * save the returned string as tasteful.yaml and pass it around.
+     *
+     * Oh, and you can decide how big the indent is and what the wordwrap
+     * for folding is.  Pretty cool -- just pass in 'false' for either if
+     * you want to use the default.
+     *
+     * Indent's default is 2 spaces, wordwrap's default is 40 characters.  And
+     * you can turn off wordwrap by passing in 0.
+     *
+     * @access public
+     * @return string
+     * @param array $array PHP array
+     * @param int $indent Pass in false to use the default, which is 2
+     * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
+     */
+    function dump($array,$indent = false,$wordwrap = false) {
+      // Dumps to some very clean YAML.  We'll have to add some more features
+      // and options soon.  And better support for folding.
+
+      // New features and options.
+      if ($indent === false or !is_numeric($indent)) {
+        $this->_dumpIndent = 2;
+      } else {
+        $this->_dumpIndent = $indent;
+      }
+
+      if ($wordwrap === false or !is_numeric($wordwrap)) {
+        $this->_dumpWordWrap = 40;
+      } else {
+        $this->_dumpWordWrap = $wordwrap;
+      }
+
+      // New YAML document
+      $string = "---\n";
+
+      // Start at the base of the array and move through it.
+      foreach ($array as $key => $value) {
+        $string .= $this->_yamlize($key,$value,0);
+      }
+      return $string;
+    }
+
+    /**** Private Properties ****/
+
+    /**#@+
+     * @access private
+     * @var mixed
+     */
+    var $_haveRefs;
+    var $_allNodes;
+    var $_allParent;
+    var $_lastIndent;
+    var $_lastNode;
+    var $_inBlock;
+    var $_isInline;
+    var $_dumpIndent;
+    var $_dumpWordWrap;
+
+    /**#@+*/
+
+    /**** Public Properties ****/
+
+    /**#@+
+     * @access public
+     * @var mixed
+     */
+    var $_nodeId;
+
+    /**#@+*/
+
+    /**** Private Methods ****/
+
+    /**
+     * Attempts to convert a key / value array item to YAML
+     * @access private
+     * @return string
+     * @param $key The name of the key
+     * @param $value The value of the item
+     * @param $indent The indent of the current node
+     */
+    function _yamlize($key,$value,$indent) {
+      if (is_array($value)) {
+        // It has children.  What to do?
+        // Make it the right kind of item
+        $string = $this->_dumpNode($key,NULL,$indent);
+        // Add the indent
+        $indent += $this->_dumpIndent;
+        // Yamlize the array
+        $string .= $this->_yamlizeArray($value,$indent);
+      } elseif ( ! is_array($value)) {
+        // It doesn't have children.  Yip.
+        $string = $this->_dumpNode($key,$value,$indent);
+      }
+      return $string;
+    }
+
+    /**
+     * Attempts to convert an array to YAML
+     * @access private
+     * @return string
+     * @param $array The array you want to convert
+     * @param $indent The indent of the current level
+     */
+    function _yamlizeArray($array,$indent) {
+      if (is_array($array)) {
+        $string = '';
+        foreach ($array as $key => $value) {
+          $string .= $this->_yamlize($key,$value,$indent);
+        }
+        return $string;
+      } else {
+        return false;
+      }
+    }
+
+    /**
+     * Returns YAML from a key and a value
+     * @access private
+     * @return string
+     * @param $key The name of the key
+     * @param $value The value of the item
+     * @param $indent The indent of the current node
+     */
+    function _dumpNode($key,$value,$indent) {
+      // do some folding here, for blocks
+      if (strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false) {
+        $value = $this->_doLiteralBlock($value,$indent);
+      } else {
+        $value  = $this->_doFolding($value,$indent);
+      }
+
+      if (is_bool($value)) {
+        $value = ($value) ? "true" : "false";
+      }
+
+      $spaces = str_repeat(' ',$indent);
+
+      if (is_int($key)) {
+        // It's a sequence
+        $string = $spaces.'- '.$value."\n";
+      } else {
+        // It's mapped
+        $string = $spaces.$key.': '.$value."\n";
+      }
+      return $string;
+    }
+
+    /**
+     * Creates a literal block for dumping
+     * @access private
+     * @return string
+     * @param $value
+     * @param $indent int The value of the indent
+     */
+    function _doLiteralBlock($value,$indent) {
+      $exploded = explode("\n",$value);
+      $newValue = '|';
+      $indent  += $this->_dumpIndent;
+      $spaces   = str_repeat(' ',$indent);
+      foreach ($exploded as $line) {
+        $newValue .= "\n" . $spaces . trim($line);
+      }
+      return $newValue;
+    }
+
+    /**
+     * Folds a string of text, if necessary
+     * @access private
+     * @return string
+     * @param $value The string you wish to fold
+     */
+    function _doFolding($value,$indent) {
+      // Don't do anything if wordwrap is set to 0
+      if ($this->_dumpWordWrap === 0) {
+        return $value;
+      }
+
+      if (strlen($value) > $this->_dumpWordWrap) {
+        $indent += $this->_dumpIndent;
+        $indent = str_repeat(' ',$indent);
+        $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent");
+        $value   = ">\n".$indent.$wrapped;
+      }
+      return $value;
+    }
+
+    /* Methods used in loading */
+
+    /**
+     * Finds and returns the indentation of a YAML line
+     * @access private
+     * @return int
+     * @param string $line A line from the YAML file
+     */
+    function _getIndent($line) {
+      preg_match('/^\s{1,}/',$line,$match);
+      if ( ! empty($match[0])) {
+        $indent = substr_count($match[0],' ');
+      } else {
+        $indent = 0;
+      }
+      return $indent;
+    }
+
+    /**
+     * Parses YAML code and returns an array for a node
+     * @access private
+     * @return array
+     * @param string $line A line from the YAML file
+     */
+    function _parseLine($line) {
+      $line = trim($line);
+
+      if(!preg_match("/\\\#/", $line)) { 
+        $line = trim(preg_replace('/#.*$/', '', $line)); 
+      }
+
+      $array = array();
+
+      if (preg_match('/^-(.*):$/',$line)) {
+        // It's a mapped sequence
+        $key         = trim(substr(substr($line,1),0,-1));
+        $array[$key] = '';
+      } elseif ($line[0] == '-' && substr($line,0,3) != '---') {
+        // It's a list item but not a new stream
+        if (strlen($line) > 1) {
+          $value   = trim(substr($line,1));
+          // Set the type of the value.  Int, string, etc
+          $value   = $this->_toType($value);
+          $array[] = $value;
+        } else {
+          $array[] = array();
+        }
+      } elseif (preg_match('/^(.+):/',$line,$key)) {
+        // It's a key/value pair most likely
+        // If the key is in double quotes pull it out
+        if (preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) {
+          $value = trim(str_replace($matches[1],'',$line));
+          $key   = $matches[2];
+        } else {
+          // Do some guesswork as to the key and the value
+          $explode = explode(':',$line);
+          $key     = trim($explode[0]);
+          array_shift($explode);
+          $value   = trim(implode(':',$explode));
+        }
+
+        // Set the type of the value.  Int, string, etc
+        $value = $this->_toType($value);
+        if (empty($key)) {
+          $array[]     = $value;
+        } else {
+          $array[$key] = $value;
+        }
+      }
+      return $array;
+    }
+
+    /**
+     * Finds the type of the passed value, returns the value as the new type.
+     * @access private
+     * @param string $value
+     * @return mixed
+     */
+    function _toType($value) {
+      if (preg_match('/^("(.*)"|\'(.*)\')/',$value,$matches)) {
+       $value = (string)preg_replace('/(\'\'|\\\\\')/',"'",end($matches));
+       $value = preg_replace('/\\\\"/','"',$value);
+      } elseif (preg_match('/^\\[(.+)\\]$/',$value,$matches)) {
+        // Inline Sequence
+
+        // Take out strings sequences and mappings
+        $explode = $this->_inlineEscape($matches[1]);
+
+        // Propogate value array
+        $value  = array();
+        foreach ($explode as $v) {
+          $value[] = $this->_toType($v);
+        }
+      } elseif (strpos($value,': ')!==false && !preg_match('/^{(.+)/',$value)) {
+          // It's a map
+          $array = explode(': ',$value);
+          $key   = trim($array[0]);
+          array_shift($array);
+          $value = trim(implode(': ',$array));
+          $value = $this->_toType($value);
+          $value = array($key => $value);
+      } elseif (preg_match("/{(.+)}$/",$value,$matches)) {
+        // Inline Mapping
+
+        // Take out strings sequences and mappings
+        $explode = $this->_inlineEscape($matches[1]);
+
+        // Propogate value array
+        $array = array();
+        foreach ($explode as $v) {
+          $array = $array + $this->_toType($v);
+        }
+        $value = $array;
+      } elseif (strtolower($value) == 'null' or $value == '' or $value == '~') {
+        $value = NULL;
+      } elseif (preg_match ('/^[0-9]+$/', $value)) {
+      // Cheeky change for compartibility with PHP < 4.2.0
+        $value = (int)$value;
+      } elseif (in_array(strtolower($value),
+                  array('true', 'on', '+', 'yes', 'y'))) {
+        $value = true;
+      } elseif (in_array(strtolower($value),
+                  array('false', 'off', '-', 'no', 'n'))) {
+        $value = false;
+      } elseif (is_numeric($value)) {
+        $value = (float)$value;
+      } else {
+        // Just a normal string, right?
+        $value = trim(preg_replace('/#(.+)$/','',$value));
+      }
+
+      return $value;
+    }
+
+    /**
+     * Used in inlines to check for more inlines or quoted strings
+     * @access private
+     * @return array
+     */
+    function _inlineEscape($inline) {
+      // There's gotta be a cleaner way to do this...
+      // While pure sequences seem to be nesting just fine,
+      // pure mappings and mappings with sequences inside can't go very
+      // deep.  This needs to be fixed.
+
+      $saved_strings = array();
+
+      // Check for strings
+      $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
+      if (preg_match_all($regex,$inline,$strings)) {
+        $saved_strings = $strings[0];
+        $inline  = preg_replace($regex,'YAMLString',$inline);
+      }
+      unset($regex);
+
+      // Check for sequences
+      if (preg_match_all('/\[(.+)\]/U',$inline,$seqs)) {
+        $inline = preg_replace('/\[(.+)\]/U','YAMLSeq',$inline);
+        $seqs   = $seqs[0];
+      }
+
+      // Check for mappings
+      if (preg_match_all('/{(.+)}/U',$inline,$maps)) {
+        $inline = preg_replace('/{(.+)}/U','YAMLMap',$inline);
+        $maps   = $maps[0];
+      }
+
+      $explode = explode(', ',$inline);
+
+
+      // Re-add the sequences
+      if ( ! empty($seqs)) {
+        $i = 0;
+        foreach ($explode as $key => $value) {
+          if (strpos($value,'YAMLSeq') !== false) {
+            $explode[$key] = str_replace('YAMLSeq',$seqs[$i],$value);
+            ++$i;
+          }
+        }
+      }
+
+      // Re-add the mappings
+      if ( ! empty($maps)) {
+        $i = 0;
+        foreach ($explode as $key => $value) {
+          if (strpos($value,'YAMLMap') !== false) {
+            $explode[$key] = str_replace('YAMLMap',$maps[$i],$value);
+            ++$i;
+          }
+        }
+      }
+
+      // Re-add the strings
+      if ( ! empty($saved_strings)) {
+        $i = 0;
+        foreach ($explode as $key => $value) {
+          while (strpos($value,'YAMLString') !== false) {
+            $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$i],$value, 1);
+            ++$i;
+            $value = $explode[$key];
+          }
+        }
+      }
+
+      return $explode;
+    }
+
+    /**
+     * Builds the PHP array from all the YAML nodes we've gathered
+     * @access private
+     * @return array
+     */
+    function _buildArray() {
+      $trunk = array();
+
+      if ( ! isset($this->_indentSort[0])) {
+        return $trunk;
+      }
+
+      foreach ($this->_indentSort[0] as $n) {
+        if (empty($n->parent)) {
+          $this->_nodeArrayizeData($n);
+          // Check for references and copy the needed data to complete them.
+          $this->_makeReferences($n);
+          // Merge our data with the big array we're building
+          $trunk = $this->_array_kmerge($trunk,$n->data);
+        }
+      }
+
+      return $trunk;
+    }
+
+    /**
+     * Traverses node-space and sets references (& and *) accordingly
+     * @access private
+     * @return bool
+     */
+    function _linkReferences() {
+      if (is_array($this->_haveRefs)) {
+        foreach ($this->_haveRefs as $node) {
+          if ( ! empty($node->data)) {
+            $key = key($node->data);
+            // If it's an array, don't check.
+            if (is_array($node->data[$key])) {
+              foreach ($node->data[$key] as $k => $v) {
+                $this->_linkRef($node,$key,$k,$v);
+              }
+            } else {
+              $this->_linkRef($node,$key);
+            }
+          }
+        }
+      }
+      return true;
+    }
+
+    function _linkRef(&$n,$key,$k = NULL,$v = NULL) {
+      if (empty($k) && empty($v)) {
+        // Look for &refs
+        if (preg_match('/^&([^ ]+)/',$n->data[$key],$matches)) {
+          // Flag the node so we know it's a reference
+          $this->_allNodes[$n->id]->ref = substr($matches[0],1);
+          $this->_allNodes[$n->id]->data[$key] =
+                   substr($n->data[$key],strlen($matches[0])+1);
+        // Look for *refs
+        } elseif (preg_match('/^\*([^ ]+)/',$n->data[$key],$matches)) {
+          $ref = substr($matches[0],1);
+          // Flag the node as having a reference
+          $this->_allNodes[$n->id]->refKey =  $ref;
+        }
+      } elseif ( ! empty($k) && !empty($v)) {
+        if (preg_match('/^&([^ ]+)/',$v,$matches)) {
+          // Flag the node so we know it's a reference
+          $this->_allNodes[$n->id]->ref = substr($matches[0],1);
+          $this->_allNodes[$n->id]->data[$key][$k] =
+                              substr($v,strlen($matches[0])+1);
+        // Look for *refs
+        } elseif (preg_match('/^\*([^ ]+)/',$v,$matches)) {
+          $ref = substr($matches[0],1);
+          // Flag the node as having a reference
+          $this->_allNodes[$n->id]->refKey =  $ref;
+        }
+      }
+    }
+
+    /**
+     * Finds the children of a node and aids in the building of the PHP array
+     * @access private
+     * @param int $nid The id of the node whose children we're gathering
+     * @return array
+     */
+    function _gatherChildren($nid) {
+      $return = array();
+      $node   =& $this->_allNodes[$nid];
+      if (is_array ($this->_allParent[$node->id])) {
+        foreach ($this->_allParent[$node->id] as $nodeZ) {
+          $z =& $this->_allNodes[$nodeZ];
+          // We found a child
+          $this->_nodeArrayizeData($z);
+          // Check for references
+          $this->_makeReferences($z);
+          // Merge with the big array we're returning
+          // The big array being all the data of the children of our parent node
+          $return = $this->_array_kmerge($return,$z->data);
+        }
+      }
+      return $return;
+    }
+
+    /**
+     * Turns a node's data and its children's data into a PHP array
+     *
+     * @access private
+     * @param array $node The node which you want to arrayize
+     * @return boolean
+     */
+    function _nodeArrayizeData(&$node) {
+      if (is_array($node->data) && $node->children == true) {
+        // This node has children, so we need to find them
+        $childs = $this->_gatherChildren($node->id);
+        // We've gathered all our children's data and are ready to use it
+        $key = key($node->data);
+        $key = empty($key) ? 0 : $key;
+        // If it's an array, add to it of course
+        if (isset ($node->data[$key])) {
+            if (is_array($node->data[$key])) {
+              $node->data[$key] = $this->_array_kmerge($node->data[$key],$childs);
+            } else {
+              $node->data[$key] = $childs;
+            }
+        } else {
+            $node->data[$key] = $childs;
+        }
+      } elseif ( ! is_array($node->data) && $node->children == true) {
+        // Same as above, find the children of this node
+        $childs       = $this->_gatherChildren($node->id);
+        $node->data   = array();
+        $node->data[] = $childs;
+      }
+
+      // We edited $node by reference, so just return true
+      return true;
+    }
+
+    /**
+     * Traverses node-space and copies references to / from this object.
+     * @access private
+     * @param object $z A node whose references we wish to make real
+     * @return bool
+     */
+    function _makeReferences(&$z) {
+      // It is a reference
+      if (isset($z->ref)) {
+        $key                = key($z->data);
+        // Copy the data to this object for easy retrieval later
+        $this->ref[$z->ref] =& $z->data[$key];
+      // It has a reference
+      } elseif (isset($z->refKey)) {
+        if (isset($this->ref[$z->refKey])) {
+          $key           = key($z->data);
+          // Copy the data from this object to make the node a real reference
+          $z->data[$key] =& $this->ref[$z->refKey];
+        }
+      }
+      return true;
+    }
+
+
+    /**
+     * Merges arrays and maintains numeric keys.
+     *
+     * An ever-so-slightly modified version of the array_kmerge() function posted
+     * to php.net by mail at nospam dot iaindooley dot com on 2004-04-08.
+     *
+     * http://us3.php.net/manual/en/function.array-merge.php#41394
+     *
+     * @access private
+     * @param array $arr1
+     * @param array $arr2
+     * @return array
+     */
+    function _array_kmerge($arr1,$arr2) {
+      if( ! is_array($arr1)) $arr1 = array();
+      if( ! is_array($arr2)) $arr2 = array();
+
+      $keys  = array_merge(array_keys($arr1),array_keys($arr2));
+      $vals  = array_merge(array_values($arr1),array_values($arr2));
+      $ret   = array();
+      foreach($keys as $key) {
+        list($unused,$val) = each($vals);
+        if (isset($ret[$key]) and is_int($key)) $ret[] = $val; else $ret[$key] = $val;
+      }
+      return $ret;
+    }
+  }
+?>
diff --git a/lib/Doctrine/TODO/Record/Generator.php b/lib/Doctrine/TODO/Record/Generator.php
new file mode 100644
index 000000000..35f31ca2a
--- /dev/null
+++ b/lib/Doctrine/TODO/Record/Generator.php
@@ -0,0 +1,286 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Record_Generator
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  Plugin
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @todo Rename. Move. Reimpl?
+ */
+abstract class Doctrine_Record_Generator
+{
+    /**
+     * @var array $_options     an array of plugin specific options
+     */
+    protected $_options = array('generateFiles' => false,
+                                'identifier'    => false,
+                                'generateFiles' => false,
+                                'table'         => false,
+                                'pluginTable'   => false,
+                                'children'      => array());
+                                
+    protected $_initialized = false;
+    /**
+     * __get
+     * an alias for getOption
+     *
+     * @param string $option
+     */
+    public function __get($option)
+    {
+        if (isset($this->_options[$option])) {
+            return $this->_options[$option];
+        }
+        return null;
+    }
+
+    /**
+     * __isset
+     *
+     * @param string $option
+     */
+    public function __isset($option) 
+    {
+        return isset($this->_options[$option]);
+    }
+
+    /**
+     * returns the value of an option
+     *
+     * @param $option       the name of the option to retrieve
+     * @return mixed        the value of the option
+     */
+    public function getOption($name)
+    {
+        if ( ! isset($this->_options[$name])) {
+            throw new Doctrine_Plugin_Exception('Unknown option ' . $name);
+        }
+        
+        return $this->_options[$name];
+    }
+
+    /**
+     * sets given value to an option
+     *
+     * @param $option       the name of the option to be changed
+     * @param $value        the value of the option
+     * @return Doctrine_Plugin  this object
+     */
+    public function setOption($name, $value)
+    {
+        $this->_options[$name] = $value;
+        
+        return $this;
+    }
+
+    public function addChild(Doctrine_Record_Generator $template)
+    {
+        $this->_options['children'][] = $template;
+    }
+
+    /**
+     * returns all options and their associated values
+     *
+     * @return array    all options as an associative array
+     */
+    public function getOptions()
+    {
+        return $this->_options;
+    }
+
+    public function initialize($table)
+    {
+    	if ($this->_initialized) {
+    	    return false;
+    	}
+        
+        $this->_initialized = true;
+
+        $this->initOptions();
+
+        $table->addGenerator($this, get_class($this));
+
+        $this->_options['table'] = $table;
+
+        $this->_options['className'] = str_replace('%CLASS%',
+                                                   $this->_options['table']->getComponentName(),
+                                                   $this->_options['className']);
+
+        // check that class doesn't exist (otherwise we cannot create it)
+        if (class_exists($this->_options['className'])) {
+            return false;
+        }
+
+        $conn = $this->_options['table']->getConnection();
+
+        $this->_table = new Doctrine_Table($this->_options['className'], $conn);
+        
+        $conn->addTable($this->_table);
+
+        $fk = $this->buildForeignKeys($this->_options['table']);
+        
+        $this->_table->setColumns($fk);
+
+        $this->buildRelation();
+
+        $this->setTableDefinition();
+        $this->setUp();
+
+        $this->generateClass($this->_table->getColumns());
+
+        $this->buildChildDefinitions();
+
+    }
+    /** 
+     * empty template method for providing the concrete plugins the ability
+     * to initialize options before the actual definition is being built
+     *
+     * @return void
+     */
+    public function initOptions()
+    {
+        
+    }
+    public function buildChildDefinitions()
+    {
+        if ( ! isset($this->_options['children'])) {
+            throw new Doctrine_Plugin_Exception("Unknown option 'children'.");
+        }
+
+        foreach ($this->_options['children'] as $child) {
+            $this->_table->addGenerator($child, get_class($child));
+
+            $child->setTable($this->_table);
+
+            $child->setUp();
+        }
+    }
+
+    /**
+     * generates foreign keys for the plugin table based on the owner table
+     *
+     * the foreign keys generated by this method can be used for 
+     * setting the relations between the owner and the plugin classes
+     *
+     * @param Doctrine_Table $table     the table object that owns the plugin
+     * @return array                    an array of foreign key definitions
+     */
+    public function buildForeignKeys($table)
+    {
+        $fk = array();
+
+        foreach ((array) $table->getIdentifier() as $column) {
+            $def = $table->getDefinitionOf($column);
+
+            unset($def['autoincrement']);
+            unset($def['sequence']);
+            unset($def['primary']);
+
+            $col = $column;
+
+            $def['primary'] = true;
+            $fk[$col] = $def;
+        }
+        return $fk;
+    }
+
+    public function buildLocalRelation()
+    {
+        $options = array('local'    => $this->_options['table']->getIdentifier(),
+                         'foreign'  => $this->_options['table']->getIdentifier(),
+                         'type'     => Doctrine_Relation::MANY);
+
+        $options['type'] = Doctrine_Relation::ONE;
+        $options['onDelete'] = 'CASCADE';
+        $options['onUpdate'] = 'CASCADE';
+
+        $this->_table->getRelationParser()->bind($this->_options['table']->getComponentName(), $options);
+    }
+    
+    public function buildForeignRelation($alias = null)
+    {
+        $options = array('local'    => $this->_options['table']->getIdentifier(),
+                         'foreign'  => $this->_options['table']->getIdentifier(),
+                         'type'     => Doctrine_Relation::MANY);
+
+        $aliasStr = '';
+
+        if ($alias !== null) {
+            $aliasStr = ' as ' . $alias;
+        }
+
+        $this->_options['table']->getRelationParser()->bind($this->_table->getComponentName() . $aliasStr,
+                                                            $options);
+    }
+
+    /**
+     * build a relation array to given table
+     *
+     * this method can be used for generating the relation from the plugin 
+     * table to the owner table
+     *
+     * @return array                    the generated relation array
+     */
+    public function buildRelation()
+    {
+    	$this->buildForeignRelation();
+        $this->buildLocalRelation();
+    }
+
+    /**
+     * generates the class definition for plugin class
+     *
+     * @param array $columns    the plugin class columns, keys representing the column names
+     *                          and values as column definitions
+     *
+     * @param array $relations  the bound relations of the plugin class
+     *
+     * @param array $options    plugin class options, keys representing the option names
+     *                          and values as option values
+     * @return void
+     */
+    public function generateClass(array $columns = array(), array $relations = array(), array $options = array())
+    {
+        $options['className'] = $this->_options['className'];
+
+        $builder = new Doctrine_Builder_Record();
+
+        if ($this->_options['generateFiles']) {
+            if (isset($this->_options['generatePath']) && $this->_options['generatePath']) {
+                $builder->setTargetPath($this->_options['generatePath']);
+
+                $builder->buildRecord($options, $columns, $relations);
+            } else {
+                throw new Doctrine_Record_Exception('If you wish to generate files then you must specify the path to generate the files in.');
+            }
+        } else {
+            $def = $builder->buildDefinition($options, $columns, $relations);
+
+            eval($def);
+        }
+    }
+}
diff --git a/lib/Doctrine/TODO/Search/Analyzer.php b/lib/Doctrine/TODO/Search/Analyzer.php
new file mode 100644
index 000000000..28b55bcd7
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Analyzer.php
@@ -0,0 +1,39 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Analyzer
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Analyzer implements Doctrine_Search_Analyzer_Interface
+{
+    public function analyze($text)
+    {
+    
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Search/Analyzer/Exception.php b/lib/Doctrine/TODO/Search/Analyzer/Exception.php
new file mode 100644
index 000000000..53829108a
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Analyzer/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+Doctrine::autoload('Doctrine_Search_Exception');
+/**
+ * Doctrine_Search_Analyzer_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Analyzer_Exception extends Doctrine_Search_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Search/Analyzer/Interface.php b/lib/Doctrine/TODO/Search/Analyzer/Interface.php
new file mode 100644
index 000000000..c810d2b3b
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Analyzer/Interface.php
@@ -0,0 +1,36 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Analyzer_Interface
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+interface Doctrine_Search_Analyzer_Interface
+{
+    public function analyze($text);
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Search/Analyzer/Standard.php b/lib/Doctrine/TODO/Search/Analyzer/Standard.php
new file mode 100644
index 000000000..aaa7d6f00
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Analyzer/Standard.php
@@ -0,0 +1,298 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Analyzer_Standard
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Analyzer_Standard implements Doctrine_Search_Analyzer_Interface
+{
+    protected static $_stopwords = array(
+                            '0',
+                            '1',
+                            '2',
+                            '3',
+                            '4',
+                            '5',
+                            '6',
+                            '7',
+                            '8',
+                            '9',
+                            '10',
+                            'a',
+                            'about',
+                            'after',
+                            'all',
+                            'almost',
+                            'along',
+                            'also',
+                            'although',
+                            'amp',
+                            'an',
+                            'and',
+                            'another',
+                            'any',
+                            'are',
+                            'area',
+                            'arent',
+                            'around',
+                            'as',
+                            'at',
+                            'available',
+                            'back',
+                            'be',
+                            'because',
+                            'been',
+                            'before',
+                            'being',
+                            'best',
+                            'better',
+                            'big',
+                            'bit',
+                            'both',
+                            'but',
+                            'by',
+                            'c',
+                            'came',
+                            'can',
+                            'capable',
+                            'control',
+                            'could',
+                            'course',
+                            'd',
+                            'dan',
+                            'day',
+                            'decided',
+                            'did',
+                            'didn',
+                            'different',
+                            'div',
+                            'do',
+                            'doesn',
+                            'don',
+                            'down',
+                            'drive',
+                            'e',
+                            'each',
+                            'easily',
+                            'easy',
+                            'edition',
+                            'either',
+                            'end',
+                            'enough',
+                            'even',
+                            'every',
+                            'example',
+                            'few',
+                            'find',
+                            'first',
+                            'for',
+                            'found',
+                            'from',
+                            'get',
+                            'go',
+                            'going',
+                            'good',
+                            'got',
+                            'gt',
+                            'had',
+                            'hard',
+                            'has',
+                            'have',
+                            'he',
+                            'her',
+                            'here',
+                            'how',
+                            'i',
+                            'if',
+                            'in',
+                            'into',
+                            'is',
+                            'isn',
+                            'it',
+                            'just',
+                            'know',
+                            'last',
+                            'left',
+                            'li',
+                            'like',
+                            'little',
+                            'll',
+                            'long',
+                            'look',
+                            'lot',
+                            'lt',
+                            'm',
+                            'made',
+                            'make',
+                            'many',
+                            'mb',
+                            'me',
+                            'menu',
+                            'might',
+                            'mm',
+                            'more',
+                            'most',
+                            'much',
+                            'my',
+                            'name',
+                            'nbsp',
+                            'need',
+                            'new',
+                            'no',
+                            'not',
+                            'now',
+                            'number',
+                            'of',
+                            'off',
+                            'old',
+                            'on',
+                            'one',
+                            'only',
+                            'or',
+                            'original',
+                            'other',
+                            'our',
+                            'out',
+                            'over',
+                            'part',
+                            'place',
+                            'point',
+                            'pretty',
+                            'probably',
+                            'problem',
+                            'put',
+                            'quite',
+                            'quot',
+                            'r',
+                            're',
+                            'really',
+                            'results',
+                            'right',
+                            's',
+                            'same',
+                            'saw',
+                            'see',
+                            'set',
+                            'several',
+                            'she',
+                            'sherree',
+                            'should',
+                            'since',
+                            'size',
+                            'small',
+                            'so',
+                            'some',
+                            'something',
+                            'special',
+                            'still',
+                            'stuff',
+                            'such',
+                            'sure',
+                            'system',
+                            't',
+                            'take',
+                            'than',
+                            'that',
+                            'the',
+                            'their',
+                            'them',
+                            'then',
+                            'there',
+                            'these',
+                            'they',
+                            'thing',
+                            'things',
+                            'think',
+                            'this',
+                            'those',
+                            'though',
+                            'through',
+                            'time',
+                            'to',
+                            'today',
+                            'together',
+                            'too',
+                            'took',
+                            'two',
+                            'up',
+                            'us',
+                            'use',
+                            'used',
+                            'using',
+                            've',
+                            'very',
+                            'want',
+                            'was',
+                            'way',
+                            'we',
+                            'well',
+                            'went',
+                            'were',
+                            'what',
+                            'when',
+                            'where',
+                            'which',
+                            'while',
+                            'white',
+                            'who',
+                            'will',
+                            'with',
+                            'would',
+                            'yet',
+                            'you',
+                            'your',
+                            'yours'
+                            );
+
+    public function analyze($text)
+    {
+    	$text = preg_replace('/[\'`ďż˝"]/', '', $text);
+        $text = preg_replace('/[^A-Za-z0-9]/', ' ', $text);
+        $text = str_replace('  ', ' ', $text);
+
+        $terms = explode(' ', $text);
+        
+        $ret = array();
+        if ( ! empty($terms)) {
+            foreach ($terms as $i => $term) {
+                if (empty($term)) {
+                    continue;
+                }
+                $lower = strtolower(trim($term));
+
+                if (in_array($lower, self::$_stopwords)) {
+                    continue;
+                }
+
+                $ret[$i] = $lower;
+            }
+        }
+        return $ret;
+    }
+}
diff --git a/lib/Doctrine/TODO/Search/Exception.php b/lib/Doctrine/TODO/Search/Exception.php
new file mode 100644
index 000000000..d6bc83c34
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+Doctrine::autoload('Doctrine_Exception');
+/**
+ * Doctrine_Search_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Search/File.php b/lib/Doctrine/TODO/Search/File.php
new file mode 100644
index 000000000..75ca6c1a6
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/File.php
@@ -0,0 +1,80 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_File extends Doctrine_Search
+{
+    /**
+     * constructor
+     *
+     * @param array $options    an array of plugin options
+     */
+    public function __construct(array $options = array())
+    {
+        parent::__construct($options);
+
+        if ( ! isset($this->_options['resource'])) {
+            $table = new Doctrine_Table('File', Doctrine_Manager::connection());
+
+            $table->setColumn('url', 'string', 255, array('primary' => true));
+        }
+
+        if (empty($this->_options['fields'])) {
+            $this->_options['fields'] = array('url', 'content');
+        }
+
+        $this->initialize($table);
+    }
+    public function buildRelation()
+    {
+    	
+    }	
+    /**
+     * indexes given directory
+     *
+     * @param string $dir   the name of the directory to index
+     * @return void
+     */
+    public function indexDirectory($dir)
+    {
+        $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
+                                                RecursiveIteratorIterator::LEAVES_ONLY);
+                                                
+        foreach ($it as $file) {
+            if (strpos($file, DIRECTORY_SEPARATOR . '.svn') !== false) {
+                continue;
+            }
+
+            $this->updateIndex(array('url' => $file->getPathName(),
+                                     'content' => file_get_contents($file)));
+        }
+    }
+}
diff --git a/lib/Doctrine/TODO/Search/Indexer.php b/lib/Doctrine/TODO/Search/Indexer.php
new file mode 100644
index 000000000..b07144d28
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Indexer.php
@@ -0,0 +1,75 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Indexer
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Indexer
+{
+    public function indexDirectory($dir)
+    {
+        if ( ! file_exists($dir)) {
+           throw new Doctrine_Search_Indexer_Exception('Unknown directory ' . $dir);
+        }
+
+        $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY);
+
+        $files = array();
+        foreach ($it as $file) {
+            $name = $file->getPathName();
+            if (strpos($name, '.svn') === false) {
+                $files[] = $name;
+            }
+        }
+
+        $q = new Doctrine_Query();
+        $q->delete()
+          ->from('Doctrine_File f')
+          ->where('f.url LIKE ?', array($dir . '%'))
+          ->execute();
+
+        // clear the index
+        $q = new Doctrine_Query();
+        $q->delete()
+          ->from('Doctrine_File_Index i')
+          ->where('i.file_id = ?')
+          ->execute();
+
+
+        $conn = Doctrine_Manager::connection();
+
+        $coll = new Doctrine_Collection('Doctrine_File');
+
+        foreach ($files as $file) {
+            $coll[]->url = $file;
+        }
+        
+        $coll->save();
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Search/Indexer/Dir.php b/lib/Doctrine/TODO/Search/Indexer/Dir.php
new file mode 100644
index 000000000..ea2dedfcf
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Indexer/Dir.php
@@ -0,0 +1,47 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Indexer_Dir
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Indexer_Dir
+{
+    public function add($dir)
+    {
+        if ( ! file_exists($dir)) {
+           throw new Doctrine_Search_Indexer_Exception('Unknown directory ' . $dir);
+        }
+
+        $it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY);
+        
+        foreach ($it as $file) {
+            $this->indexFile($file);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Search/Indexer/Exception.php b/lib/Doctrine/TODO/Search/Indexer/Exception.php
new file mode 100644
index 000000000..3595144cf
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Indexer/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Indexer
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Indexer_Exception extends Doctrine_Search_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Search/Listener.php b/lib/Doctrine/TODO/Search/Listener.php
new file mode 100644
index 000000000..6e97ccb1e
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Listener.php
@@ -0,0 +1,56 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Listener
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Listener extends Doctrine_Record_Listener 
+{
+    protected $_search;
+
+    public function __construct(Doctrine_Search $search)
+    {
+        $this->_search = $search;
+    }
+
+    public function preUpdate(Doctrine_Event $event)
+    {
+    }
+
+    public function postUpdate(Doctrine_Event $event)
+    {
+
+    }
+    public function postInsert(Doctrine_Event $event)
+    {
+        $record = $event->getInvoker();
+        
+        $this->_search->updateIndex($record->toArray());
+    }
+}
diff --git a/lib/Doctrine/TODO/Search/Parser.php b/lib/Doctrine/TODO/Search/Parser.php
new file mode 100644
index 000000000..8710e1cd2
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Parser.php
@@ -0,0 +1,41 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Parser_Standard
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Parser
+{
+    public function parse($file)
+    {
+        $contents = file_get_contents($file);
+        
+        return array('url' => $file, 'contents' => $contents);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Search/Query.php b/lib/Doctrine/TODO/Search/Query.php
new file mode 100644
index 000000000..466574e99
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Query.php
@@ -0,0 +1,235 @@
+<?php
+/*
+ *  $Id: Hook.php 1939 2007-07-05 23:47:48Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Query
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Query
+{
+
+    /**
+     * @var Doctrine_Table $_table          the index table
+     */
+    protected $_table = array();
+    
+    protected $_sql = '';
+    
+    protected $_params = array();
+    
+    protected $_words = array();
+    
+    protected $_tokenizer;
+
+    protected $_condition;
+
+    /**
+     * @param Doctrine_Table $_table        the index table
+     */
+    public function __construct($table)
+    {
+        if (is_string($table)) {
+           $table = Doctrine_Manager::table($table);
+        } else {
+            if ( ! $table instanceof Doctrine_Table) {
+                throw new Doctrine_Search_Exception('Invalid argument type. Expected instance of Doctrine_Table.');
+            }
+        }
+
+        $this->_tokenizer = new Doctrine_Query_Tokenizer();
+        $this->_table = $table;
+
+        $foreignId = current(array_diff($this->_table->getColumnNames(), array('keyword', 'field', 'position')));
+
+        $this->_condition = $foreignId . ' %s (SELECT ' . $foreignId . ' FROM ' . $this->_table->getTableName() . ' WHERE ';
+    }
+
+
+    public function query($text)
+    {
+        $text = trim($text);
+
+        $foreignId = current(array_diff($this->_table->getColumnNames(), array('keyword', 'field', 'position')));
+
+        $weighted = false;
+        if (strpos($text, '^') === false) {
+            $select = 'SELECT COUNT(keyword) AS relevance, ' . $foreignId;
+            $from = 'FROM ' . $this->_table->getTableName();
+        } else {
+            // organize terms according weights
+            $weighted = true;
+
+            $select = 'SELECT SUM(sub_relevance) AS relevance, ' . $foreignId;
+            $from = 'FROM ' ;
+        }
+        
+        $where = 'WHERE ';
+        $where .= $this->parseClause($text);
+
+        $groupby = 'GROUP BY ' . $foreignId;
+        $orderby = 'ORDER BY relevance DESC';
+
+        $this->_sql = $select . ' ' . $from . ' ' . $where . ' ' . $groupby . ' ' . $orderby;
+    }
+
+    public function parseClause($originalClause, $recursive = false)
+    {
+        $clause = $this->_tokenizer->bracketTrim($originalClause);
+        
+        $brackets = false;
+
+        if ($clause !== $originalClause) {
+            $brackets = true;
+        }
+
+        $foreignId = current(array_diff($this->_table->getColumnNames(), array('keyword', 'field', 'position')));
+        
+        $terms = $this->_tokenizer->sqlExplode($clause, ' OR ', '(', ')');
+
+        $ret = array();
+
+        if (count($terms) > 1) {
+            $leavesOnly = true;
+
+            foreach ($terms as $k => $term) {
+                if ($this->isExpression($term)) {
+                    $ret[$k] = $this->parseClause($term, true);
+                    $leavesOnly = false;
+                } else {
+                    $ret[$k] = $this->parseTerm($term);
+                }
+            }
+
+            $return = implode(' OR ', $ret);
+
+            if ($leavesOnly && $recursive) {
+                $return = sprintf($this->_condition, 'IN') . $return . ')';
+                $brackets = false;
+            }
+        } else {
+            $terms = $this->_tokenizer->sqlExplode($clause, ' ', '(', ')');
+            
+            if (count($terms) === 1 && ! $recursive) {
+                $return = $this->parseTerm($clause);
+            } else {
+                foreach ($terms as $k => $term) {
+                    $term = trim($term);
+    
+                    if ($term === 'AND') {
+                        continue;
+                    }
+    
+                    if (substr($term, 0, 1) === '-') {
+                        $operator = 'NOT IN';
+                        $term = substr($term, 1);
+                    } else {
+                        $operator = 'IN';
+                    }
+    
+                    if ($this->isExpression($term)) {
+                        $ret[$k] = $this->parseClause($term, true);
+                    } else {
+                        $ret[$k] = sprintf($this->_condition, $operator) . $this->parseTerm($term) . ')';
+                    }
+                }
+                $return = implode(' AND ', $ret);
+            }
+        }
+
+        if ($brackets) {
+            return '(' . $return . ')';
+        } else {
+            return $return;
+        }
+    }
+    public function isExpression($term)
+    {
+        if (strpos($term, '(') !== false) {
+            return true;
+        } else {
+            $terms = $this->_tokenizer->quoteExplode($term);
+            
+            return (count($terms) > 1);
+        }
+    }
+
+    public function parseTerm($term)
+    {
+        $negation = false;
+
+        if (strpos($term, "'") === false) {
+            $where = $this->parseWord($term);
+        } else {
+            $term = trim($term, "' ");
+
+            $terms = $this->_tokenizer->quoteExplode($term);
+            $where = $this->parseWord($terms[0]);
+
+            foreach ($terms as $k => $word) {
+                if ($k === 0) {
+                    continue;
+                }
+                $where .= ' AND (position + ' . $k . ') = (SELECT position FROM ' . $this->_table->getTableName() . ' WHERE ' . $this->parseWord($word) . ')';
+            }
+        }
+        return $where;
+    }
+    public function parseWord($word)
+    {
+        $this->_words[] = str_replace('*', '', $word);
+
+        if (strpos($word, '?') !== false ||
+            strpos($word, '*') !== false) {
+
+            $word = str_replace('*', '%', $word);
+
+            $where = 'keyword LIKE ?';
+
+            $params = array($word);
+        } else {
+            $where = 'keyword = ?';
+        }
+
+        $this->_params[] = $word;
+
+        return $where;
+    }
+
+    public function getWords()
+    {
+        return $this->_words;
+    }
+    public function getParams()
+    {
+        return $this->_params;
+    }
+    public function getSql()
+    {
+        return $this->_sql;
+    }
+}
diff --git a/lib/Doctrine/TODO/Search/Record.php b/lib/Doctrine/TODO/Search/Record.php
new file mode 100644
index 000000000..95015c003
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Record.php
@@ -0,0 +1,47 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Record
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Record extends Doctrine_Template
+{
+    public function setTableDefinition()
+    {
+        $this->hasColumn('keyword', 'string', 250, array('notnull' => true));
+        $this->hasColumn('field', 'string', 50, array('notnull' => true));
+        $this->hasColumn('position', 'integer', 8);
+        // depending on the identifiers of the owner record this record 
+        // has also one to many foreign key columns
+    }
+    public function setUp()
+    {
+        $this->hasOne('[Component]', array('onDelete' => 'CASCADE'));
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Search/Scorer.php b/lib/Doctrine/TODO/Search/Scorer.php
new file mode 100644
index 000000000..d8ac7b8d0
--- /dev/null
+++ b/lib/Doctrine/TODO/Search/Scorer.php
@@ -0,0 +1,63 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Search_Scorer
+ *
+ * @package     Doctrine
+ * @subpackage  Search
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Search_Scorer
+{
+    protected $_resultSet;
+    
+    protected $_components = array();
+
+    public function __construct($resultSet)
+    {
+        $this->_resultSet = $resultSet;
+    }
+
+    public function addComponent($component)
+    {
+        $this->_components[] = $component;
+    }
+
+    public function process()
+    {
+        foreach ($this->_resultSet as $mainRow) {
+            if (isset($mainRow[$component])) {
+                if ( ! is_array($mainRow[$component])) {
+                    throw new Doctrine_Search_Exception('Wrong data type in result set.');
+                }
+                
+                foreach ($mainRow[$component] as $indexRow) {
+
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/BuildAll.php b/lib/Doctrine/TODO/Task/BuildAll.php
new file mode 100644
index 000000000..bb71c7f69
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/BuildAll.php
@@ -0,0 +1,65 @@
+<?php
+/*
+ *  $Id: BuildAll.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_BuildAll
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_BuildAll extends Doctrine_Task
+{
+    public $description          =   'Calls generate-models-from-yaml, create-db, and create-tables',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array();
+    
+    protected $models,
+              $tables;
+    
+    public function __construct($dispatcher = null)
+    {
+        parent::__construct($dispatcher);
+        
+        $this->models = new Doctrine_Task_GenerateModelsYaml($this->dispatcher);
+        $this->createDb = new Doctrine_Task_CreateDb($this->dispatcher);
+        $this->tables = new Doctrine_Task_CreateTables($this->dispatcher);
+        
+        $this->requiredArguments = array_merge($this->requiredArguments, $this->models->requiredArguments, $this->createDb->requiredArguments, $this->tables->requiredArguments);
+        $this->optionalArguments = array_merge($this->optionalArguments, $this->models->optionalArguments, $this->createDb->optionalArguments, $this->tables->optionalArguments);
+    }
+    
+    public function execute()
+    {
+        $this->models->setArguments($this->getArguments());
+        $this->models->execute();
+        
+        $this->createDb->setArguments($this->getArguments());
+        $this->createDb->execute();
+        
+        $this->tables->setArguments($this->getArguments());
+        $this->tables->execute();
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/BuildAllLoad.php b/lib/Doctrine/TODO/Task/BuildAllLoad.php
new file mode 100644
index 000000000..b4e50311b
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/BuildAllLoad.php
@@ -0,0 +1,58 @@
+<?php
+/*
+ *  $Id: BuildAllLoad.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_BuildAllLoad
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_BuildAllLoad extends Doctrine_Task
+{
+    public $description          =   'Calls build-all, and load-data',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array();
+    
+    public function __construct($dispatcher = null)
+    {
+        parent::__construct($dispatcher);
+
+        $this->buildAll = new Doctrine_Task_BuildAll($this->dispatcher);
+        $this->loadData = new Doctrine_Task_LoadData($this->dispatcher);
+        
+        $this->requiredArguments = array_merge($this->requiredArguments, $this->buildAll->requiredArguments, $this->loadData->requiredArguments);
+        $this->optionalArguments = array_merge($this->optionalArguments, $this->buildAll->optionalArguments, $this->loadData->optionalArguments);
+    }
+    
+    public function execute()
+    {
+        $this->buildAll->setArguments($this->getArguments());
+        $this->buildAll->execute();
+        
+        $this->loadData->setArguments($this->getArguments());
+        $this->loadData->execute();
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/BuildAllReload.php b/lib/Doctrine/TODO/Task/BuildAllReload.php
new file mode 100644
index 000000000..efd258dc2
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/BuildAllReload.php
@@ -0,0 +1,58 @@
+<?php
+/*
+ *  $Id: BuildAllReload.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_BuildAllReload
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_BuildAllReload extends Doctrine_Task
+{
+    public $description          =   'Calls rebuild-db and load-data',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array();
+    
+    public function __construct($dispatcher = null)
+    {
+        parent::__construct($dispatcher);
+
+        $this->rebuildDb = new Doctrine_Task_RebuildDb($this->dispatcher);
+        $this->loadData = new Doctrine_Task_LoadData($this->dispatcher);
+        
+        $this->requiredArguments = array_merge($this->requiredArguments, $this->rebuildDb->requiredArguments, $this->loadData->requiredArguments);
+        $this->optionalArguments = array_merge($this->optionalArguments, $this->rebuildDb->optionalArguments, $this->loadData->optionalArguments);
+    }
+    
+    public function execute()
+    {
+        $this->rebuildDb->setArguments($this->getArguments());
+        $this->rebuildDb->execute();
+        
+        $this->loadData->setArguments($this->getArguments());
+        $this->loadData->execute();
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/Compile.php b/lib/Doctrine/TODO/Task/Compile.php
new file mode 100644
index 000000000..d1b4ceaab
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/Compile.php
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: Task.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_Compile
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_Compile extends Doctrine_Task
+{
+    public $description          =   'Compile doctrine classes in to one single php file',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array('drivers'        =>  'Specify list of drivers you wish to compile. Ex: mysql|mssql|sqlite',
+                                           'compiled_path'  =>  'The path where you want to write the compiled doctrine libs.');
+    
+    public function execute()
+    {
+        $compiledPath = Doctrine_Compiler::compile($this->getArgument('compiled_path'), $this->getArgument('drivers', array()));
+
+        $this->notify('Compiled Doctrine successfully to: ' . $compiledPath);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/CreateDb.php b/lib/Doctrine/TODO/Task/CreateDb.php
new file mode 100644
index 000000000..c00b577fa
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/CreateDb.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ *  $Id: CreateDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_CreateDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_CreateDb extends Doctrine_Task
+{
+    public $description          =   'Create all databases for your connections. If the database already exists, nothing happens.',
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        $results = Doctrine::createDatabases();
+        
+        foreach ($results as $name => $result) {
+            $msg = $result instanceof Exception ? 'Could not create database for connection: "' .$name . '." Failed with exception: ' . $result->getMessage():$result;
+            
+            $this->notify($msg);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/CreateTables.php b/lib/Doctrine/TODO/Task/CreateTables.php
new file mode 100644
index 000000000..213e7b335
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/CreateTables.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: CreateTables.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_CreateTables
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_CreateTables extends Doctrine_Task
+{
+    public $description          =   'Create tables for all existing database connections. If table exists nothing happens.',
+           $requiredArguments    =   array('models_path' => 'Specify path to your models directory.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::createTablesFromModels($this->getArgument('models_path'));
+        
+        $this->dispatcher->notify('Created tables successfully');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/Dql.php b/lib/Doctrine/TODO/Task/Dql.php
new file mode 100644
index 000000000..0f706399f
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/Dql.php
@@ -0,0 +1,76 @@
+<?php
+/*
+ *  $Id: Dql.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_Dql
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_Dql extends Doctrine_Task
+{
+    public $description          =   'Execute dql query and display the results',
+           $requiredArguments    =   array('models_path'    =>  'Specify path to your Doctrine_Record definitions.',
+                                           'dql_query'      =>  'Specify the complete dql query to execute.'),
+           $optionalArguments    =   array('params'         =>  'Comma separated list of the params to replace the ? tokens in the dql');
+
+    public function execute()
+    {
+        Doctrine::loadModels($this->getArgument('models_path'));
+
+        $dql = $this->getArgument('dql_query');
+
+        $query = new Doctrine_Query();
+
+        $params = $this->getArgument('params');
+        $params = $params ? explode(',', $params):array();
+
+        $this->notify('executing: "' . $dql . '" (' . implode(', ', $params) . ')');
+
+        $results = $query->query($dql);
+
+        $this->_printResults($results);
+    }
+
+    protected function _printResults($data)
+    {
+        $array = $data->toArray(true);
+
+        $yaml = Doctrine_Parser::dump($array, 'yml');
+        $lines = explode("\n", $yaml);
+
+        unset($lines[0]);
+        $lines[1] = $data->getTable()->getOption('name') . ':';
+
+        foreach ($lines as $yamlLine) {
+            $line = trim($yamlLine);
+
+            if ($line) {
+                $this->notify($yamlLine);
+            }
+        }
+    }
+}
diff --git a/lib/Doctrine/TODO/Task/DropDb.php b/lib/Doctrine/TODO/Task/DropDb.php
new file mode 100644
index 000000000..7eb1ab092
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/DropDb.php
@@ -0,0 +1,59 @@
+<?php
+/*
+ *  $Id: DropDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_DropDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_DropDb extends Doctrine_Task
+{
+    public $description          =   'Drop database for all existing connections',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array('force'  =>  'Whether or not to force the drop database task');
+
+    public function execute()
+    {
+        if ( ! $this->getArgument('force')) {
+            $answer = $this->ask('Are you sure you wish to drop your databases? (y/n)');
+
+            if ($answer != 'y') {
+                $this->notify('Successfully cancelled');
+
+                return;
+            }
+        }
+
+        $results = Doctrine::dropDatabases();
+
+        foreach ($results as $name => $result) {
+            $msg = $result instanceof Exception ? 'Could not drop database for connection: "' .$name . '." Failed with exception: ' . $result->getMessage():$result;
+
+            $this->notify($msg);
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/DumpData.php b/lib/Doctrine/TODO/Task/DumpData.php
new file mode 100644
index 000000000..dddd4cefa
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/DumpData.php
@@ -0,0 +1,54 @@
+<?php
+/*
+ *  $Id: GenerateSql.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_DumpData
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_DumpData extends Doctrine_Task
+{
+    public $description          =   'Dump data to a yaml data fixture file.',
+           $requiredArguments    =   array('data_fixtures_path' =>  'Specify path to write the yaml data fixtures file to.',
+                                           'models_path'        =>  'Specify path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::loadModels($this->getArgument('models_path'));
+        
+        $path = $this->getArgument('data_fixtures_path');
+        
+        if (is_array($path)) {
+          $path = $path[0];
+        }
+        
+        Doctrine::dumpData($path);
+        
+        $this->dispatcher->notify(sprintf('Dumped data successfully to: %s', $path));
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/Exception.php b/lib/Doctrine/TODO/Task/Exception.php
new file mode 100644
index 000000000..febadc321
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/GenerateMigration.php b/lib/Doctrine/TODO/Task/GenerateMigration.php
new file mode 100644
index 000000000..29075257a
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/GenerateMigration.php
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: GenerateMigration.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateMigration
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateMigration extends Doctrine_Task
+{
+    public $description          =   'Generate new migration class definition',
+           $requiredArguments    =   array('class_name'      => 'Name of the migration class to generate',
+                                           'migrations_path' => 'Specify the complete path to your migration classes folder.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::generateMigrationClass($this->getArgument('class_name'), $this->getArgument('migrations_path'));
+        
+        $this->dispatcher->notify(sprintf('Generated migration class: %s successfully to %s', $this->getArgument('class_name'), $this->getArgument('migrations_path')));
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/GenerateMigrationsDb.php b/lib/Doctrine/TODO/Task/GenerateMigrationsDb.php
new file mode 100644
index 000000000..b26639398
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/GenerateMigrationsDb.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: GenerateMigrationsDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateMigrationsDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateMigrationsDb extends Doctrine_Task
+{
+    public $description          =   'Generate migration classes for an existing database',
+           $requiredArguments    =   array('migrations_path' => 'Specify the complete path to your migration classes folder.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::generateMigrationsFromDb($this->getArgument('migrations_path'));
+        
+        $this->dispatcher->notify('Generated migration classes successfully from database');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/GenerateMigrationsModels.php b/lib/Doctrine/TODO/Task/GenerateMigrationsModels.php
new file mode 100644
index 000000000..e2f17de9b
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/GenerateMigrationsModels.php
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: GenerateMigrationsModels.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateMigrationsModels
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateMigrationsModels extends Doctrine_Task
+{
+    public $description          =   'Generate migration classes for an existing set of models',
+           $requiredArguments    =   array('migrations_path' => 'Specify the path to your migration classes folder.',
+                                           'models_path'     => 'Specify the path to your doctrine models folder.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {   
+        Doctrine::generateMigrationsFromModels($this->getArgument('migrations_path'), $this->getArgument('models_path'));
+        
+        $this->dispatcher->notify('Generated migration classes successfully from models');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/GenerateModelsDb.php b/lib/Doctrine/TODO/Task/GenerateModelsDb.php
new file mode 100644
index 000000000..afe3ff01a
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/GenerateModelsDb.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: GenerateModelsDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateModelsDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateModelsDb extends Doctrine_Task
+{
+    public $description          =   'Generates your Doctrine_Record definitions from your existing database connections.',
+           $requiredArguments    =   array('models_path'    =>  'Specify path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array('connection'     =>  'Optionally specify a single connection to generate the models for.');
+    
+    public function execute()
+    {
+        Doctrine::generateModelsFromDb($this->getArgument('models_path'), (array) $this->getArgument('connection'));
+        
+        $this->dispatcher->notify('Generated models successfully from databases');
+    }
+}
diff --git a/lib/Doctrine/TODO/Task/GenerateModelsYaml.php b/lib/Doctrine/TODO/Task/GenerateModelsYaml.php
new file mode 100644
index 000000000..79b6098cf
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/GenerateModelsYaml.php
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: GenerateModelsYaml.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateModelsYaml
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateModelsYaml extends Doctrine_Task
+{
+    public $description          =   'Generates your Doctrine_Record definitions from a Yaml schema file',
+           $requiredArguments    =   array('yaml_schema_path'   =>  'Specify the complete directory path to your yaml schema files.',
+                                           'models_path'        =>  'Specify complete path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::generateModelsFromYaml($this->getArgument('yaml_schema_path'), $this->getArgument('models_path'));
+        
+        $this->notify('Generated models successfully from YAML schema');
+    }
+}
diff --git a/lib/Doctrine/TODO/Task/GenerateSql.php b/lib/Doctrine/TODO/Task/GenerateSql.php
new file mode 100644
index 000000000..e67c620fa
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/GenerateSql.php
@@ -0,0 +1,56 @@
+<?php
+/*
+ *  $Id: GenerateSql.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateSql
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateSql extends Doctrine_Task
+{
+    public $description          =   'Generate sql for all existing database connections.',
+           $requiredArguments    =   array('models_path'    =>  'Specify complete path to your Doctrine_Record definitions.',
+                                           'sql_path'       =>  'Path to write the generated sql.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        if (is_dir($this->getArgument('sql_path'))) {
+            $path = $this->getArgument('sql_path') . DIRECTORY_SEPARATOR . 'schema.sql';
+        } else if (is_file($this->getArgument('sql_path'))) {
+            $path = $this->getArgument('sql_path');
+        } else {
+            throw new Doctrine_Task_Exception('Invalid sql path.');
+        }
+        
+        $sql = Doctrine::generateSqlFromModels($this->getArgument('models_path'));
+        
+        file_put_contents($path, $sql);
+        
+        $this->dispatcher->notify('Generated SQL successfully for models');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/GenerateYamlDb.php b/lib/Doctrine/TODO/Task/GenerateYamlDb.php
new file mode 100644
index 000000000..2ae2a014d
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/GenerateYamlDb.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: GenerateYamlDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateYamlDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateYamlDb extends Doctrine_Task
+{
+    public $description          =   'Generates a Yaml schema file from an existing database',
+           $requiredArguments    =   array('yaml_schema_path'   =>  'Specify the path to your yaml schema files.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::generateYamlFromDb($this->getArgument('yaml_schema_path'));
+        
+        $this->dispatcher->notify('Generate YAML schema successfully from database');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/GenerateYamlModels.php b/lib/Doctrine/TODO/Task/GenerateYamlModels.php
new file mode 100644
index 000000000..5cb55b2b6
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/GenerateYamlModels.php
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: GenerateYamlModels.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_GenerateFromModels
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_GenerateYamlModels extends Doctrine_Task
+{
+    public $description          =   'Generates a Yaml schema file from existing Doctrine_Record definitions',
+           $requiredArguments    =   array('yaml_schema_path'   =>  'Specify the complete directory path to your yaml schema files.',
+                                           'models_path'        =>  'Specify complete path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::generateYamlFromModels($this->getArgument('yaml_schema_path'), $this->getArgument('models_path'));
+        
+        $this->dispatcher->notify('Generated YAML schema successfully from models');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/LoadData.php b/lib/Doctrine/TODO/Task/LoadData.php
new file mode 100644
index 000000000..84078207a
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/LoadData.php
@@ -0,0 +1,47 @@
+<?php
+/*
+ *  $Id: LoadData.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_LoadData
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_LoadData extends Doctrine_Task
+{
+    public $description          =   'Load data from a yaml data fixture file.',
+           $requiredArguments    =   array('data_fixtures_path' =>  'Specify the complete path to load the yaml data fixtures files from.',
+                                           'models_path'        =>  'Specify path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array();
+    
+    public function execute()
+    {
+        Doctrine::loadModels($this->getArgument('models_path'));
+        Doctrine::loadData($this->getArgument('data_fixtures_path'));
+        
+        $this->dispatcher->notify('Data was successfully loaded');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/LoadDummyData.php b/lib/Doctrine/TODO/Task/LoadDummyData.php
new file mode 100644
index 000000000..81c0f80e2
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/LoadDummyData.php
@@ -0,0 +1,47 @@
+<?php
+/*
+ *  $Id: LoadDummyData.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_LoadDummyData
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_LoadDummyData extends Doctrine_Task
+{
+    public $description          =   'Load data from a yaml data fixture file.',
+           $requiredArguments    =   array('models_path'    =>  'Specify path to your Doctrine_Record definitions.'),
+           $optionalArguments    =   array('append'         =>  'Whether or not to append the data or to delete all data before loading.',
+                                           'num'            =>  'Number of records to populate for each model.');
+    
+    public function execute()
+    {
+        Doctrine::loadModels($this->getArgument('models_path'));
+        Doctrine::loadDummyData($this->getArgument('append') ? true:false, $this->getArgument('num') ? $this->getArgument('num'):5);
+    
+        $this->dispatcher->notify('Dummy data was successfully loaded');
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/Migrate.php b/lib/Doctrine/TODO/Task/Migrate.php
new file mode 100644
index 000000000..eb14449d1
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/Migrate.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: Migrate.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_Migrate
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_Migrate extends Doctrine_Task
+{
+    public $description          =   'Migrate database to latest version or the specified version',
+           $requiredArguments    =   array('migrations_path' => 'Specify path to your migrations directory.'),
+           $optionalArguments    =   array('version' => 'Version to migrate to. If you do not specify, the db will be migrated from the current version to the latest.');
+    
+    public function execute()
+    {
+        $version = Doctrine::migrate($this->getArgument('migrations_path'), $this->getArgument('version'));
+        
+        $this->dispatcher->notify('migrated successfully to version #' . $version);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Task/RebuildDb.php b/lib/Doctrine/TODO/Task/RebuildDb.php
new file mode 100644
index 000000000..e374136da
--- /dev/null
+++ b/lib/Doctrine/TODO/Task/RebuildDb.php
@@ -0,0 +1,58 @@
+<?php
+/*
+ *  $Id: RebuildDb.php 2761 2007-10-07 23:42:29Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Task_RebuildDb
+ *
+ * @package     Doctrine
+ * @subpackage  Task
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 2761 $
+ * @author      Jonathan H. Wage <jwage@mac.com>
+ */
+class Doctrine_Task_RebuildDb extends Doctrine_Task
+{
+    public $description          =   'Drops and re-creates databases',
+           $requiredArguments    =   array(),
+           $optionalArguments    =   array();
+    
+    public function __construct($dispatcher = null)
+    {
+        parent::__construct($dispatcher);
+        
+        $this->dropDb = new Doctrine_Task_DropDb($this->dispatcher);
+        $this->buildAll = new Doctrine_Task_BuildAll($this->dispatcher);
+        
+        $this->requiredArguments = array_merge($this->requiredArguments, $this->dropDb->requiredArguments, $this->buildAll->requiredArguments);
+        $this->optionalArguments = array_merge($this->optionalArguments, $this->dropDb->optionalArguments, $this->buildAll->optionalArguments);
+    }
+    
+    public function execute()
+    {
+        $this->dropDb->setArguments($this->getArguments());
+        $this->dropDb->execute();
+        
+        $this->buildAll->setArguments($this->getArguments());
+        $this->buildAll->execute();
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Template/Geographical.php b/lib/Doctrine/TODO/Template/Geographical.php
new file mode 100644
index 000000000..4fc1cb46f
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/Geographical.php
@@ -0,0 +1,120 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Geographical
+ *
+ * Easily add created and updated at timestamps to your doctrine records
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Geographical extends Doctrine_Template
+{
+    /**
+     * Array of timestampable options
+     *
+     * @var string
+     */
+    protected $_options = array('latitude' =>  array('name'     =>  'latitude',
+                                                     'type'     =>  'float',
+                                                     'size'     =>  4,
+                                                     'options'  =>  array()),
+                                'longitude' => array('name'     =>  'longitude',
+                                                     'type'     =>  'float',
+                                                     'size'     =>  4,
+                                                     'options'  =>  array()));
+
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options)
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    /**
+     * setTableDefinition
+     *
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+        $this->hasColumn($this->_options['latitude']['name'], $this->_options['latitude']['type'], $this->_options['latitude']['size'], $this->_options['latitude']['options']);
+        $this->hasColumn($this->_options['longitude']['name'], $this->_options['longitude']['type'], $this->_options['longitude']['size'], $this->_options['longitude']['options']);
+    }
+
+    public function getDistanceQuery()
+    {
+        $invoker = $this->getInvoker();
+        $query = $invoker->getTable()->createQuery();
+
+        $rootAlias = $query->getRootAlias();
+        $latName = $this->_options['latitude']['name'];
+        $longName = $this->_options['longitude']['name'];
+
+        $query->addSelect($rootAlias . '.*');
+
+        $sql = "((ACOS(SIN(%s * PI() / 180) * SIN(" . $rootAlias . "." . $latName . " * PI() / 180) + COS(%s * PI() / 180) * COS(" . $rootAlias . "." . $latName . " * PI() / 180) * COS((%s - " . $rootAlias . "." . $longName . ") * PI() / 180)) * 180 / PI()) * 60 * %s) as %s";
+
+        $milesSql = sprintf($sql, number_format($invoker->get('latitude'), 1), $invoker->get('latitude'), $invoker->get('longitude'), '1.1515', 'miles');
+        $query->addSelect($milesSql);
+
+        $kilometersSql = sprintf($sql, number_format($invoker->get('latitude'), 1), $invoker->get('latitude'), $invoker->get('longitude'), '1.1515 * 1.609344', 'kilometers');
+        $query->addSelect($kilometersSql);
+
+        return $query;
+    }
+
+    public function getDistance(Doctrine_Entity $record, $kilometers = false)
+    {
+        $query = $this->getDistanceQuery($kilometers);
+        
+        $conditions = array();
+        $values = array();
+        foreach ((array) $record->getTable()->getIdentifier() as $id) {
+            $conditions[] = $query->getRootAlias() . '.' . $id . ' = ?';
+            $values[] = $record->get($id);
+        }
+
+        $where = implode(' AND ', $conditions);
+
+        $query->addWhere($where, $values);
+
+        $query->limit(1);
+
+        $result = $query->execute()->getFirst();
+        
+        if (isset($result['kilometers']) && $result['miles']) {
+            return $kilometers ? $result->get('kilometers'):$result->get('miles');
+        } else {
+            return 0;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Template/I18n.php b/lib/Doctrine/TODO/Template/I18n.php
new file mode 100644
index 000000000..72c019366
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/I18n.php
@@ -0,0 +1,64 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_I18n
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_I18n extends Doctrine_Template
+{
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        $this->_plugin = new Doctrine_I18n($options);
+    }
+    /**
+     * setUp
+     *
+     * @return void
+     */
+    public function setUp()
+    {
+        $this->_plugin->initialize($this->_table); 
+    }
+
+    /**
+     * getI18n
+     *
+     * @return void
+     */
+    public function getI18n()
+    {
+        return $this->_plugin;
+    }
+}
diff --git a/lib/Doctrine/TODO/Template/Listener/Sluggable.php b/lib/Doctrine/TODO/Template/Listener/Sluggable.php
new file mode 100644
index 000000000..5da04ff99
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/Listener/Sluggable.php
@@ -0,0 +1,79 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Listener_Sluggable
+ *
+ * Easily create a slug for each record based on a specified set of fields
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Listener_Sluggable extends Doctrine_Record_Listener
+{
+    /**
+     * Array of timestampable options
+     *
+     * @var string
+     */
+    protected $_options = array();
+
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options)
+    {
+        $this->_options = $options;
+    }
+
+    public function preInsert(Doctrine_Event $event)
+    {
+        $name = $this->_options['name'];
+
+        $record = $event->getInvoker();
+
+        if (!$record->$name) {
+            $record->$name = $this->buildSlug($record);
+        }
+    }
+
+    protected function buildSlug($record)
+    {
+        if (empty($this->_options['fields'])) {
+            $value = (string) $record;
+        } else {
+            $value = '';
+            foreach ($this->_options['fields'] as $field) {
+                $value .= $record->$field . ' ';
+            }
+        }
+
+        return Doctrine_Inflector::urlize($value);
+    }
+}
diff --git a/lib/Doctrine/TODO/Template/Listener/Timestampable.php b/lib/Doctrine/TODO/Template/Listener/Timestampable.php
new file mode 100644
index 000000000..d330b6c70
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/Listener/Timestampable.php
@@ -0,0 +1,110 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Listener_Timestampable
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Listener_Timestampable extends Doctrine_Record_Listener
+{
+    /**
+     * Array of timestampable options
+     *
+     * @var string
+     */
+    protected $_options = array();
+
+    /**
+     * __construct
+     *
+     * @param string $options 
+     * @return void
+     */
+    public function __construct(array $options)
+    {
+        $this->_options = $options;
+    }
+
+    /**
+     * preInsert
+     *
+     * @param object $Doctrine_Event 
+     * @return void
+     */
+    public function preInsert(Doctrine_Event $event)
+    {
+        if( ! $this->_options['created']['disabled']) {
+            $createdName = $this->_options['created']['name'];
+            $event->getInvoker()->$createdName = $this->getTimestamp('created');
+        }
+
+        if( ! $this->_options['updated']['disabled'] && $this->_options['updated']['onInsert']) {
+            $updatedName = $this->_options['updated']['name'];
+            $event->getInvoker()->$updatedName = $this->getTimestamp('updated');
+        }
+    }
+
+    /**
+     * preUpdate
+     *
+     * @param object $Doctrine_Event 
+     * @return void
+     */
+    public function preUpdate(Doctrine_Event $event)
+    {
+        if( ! $this->_options['updated']['disabled']) {
+            $updatedName = $this->_options['updated']['name'];
+            $event->getInvoker()->$updatedName = $this->getTimestamp('updated');
+        }
+    }
+
+    /**
+     * getTimestamp
+     *
+     * Gets the timestamp in the correct format
+     *
+     * @param string $type 
+     * @return void
+     */
+    public function getTimestamp($type)
+    {
+        $options = $this->_options[$type];
+
+        if ($options['expression'] !== false && is_string($options['expression'])) {
+            return new Doctrine_Expression($options['expression']);
+        } else {
+            if ($options['type'] == 'date') {
+                return date($options['format'], time());
+            } else if ($options['type'] == 'timestamp') {
+                return date($options['format'], time());
+            } else {
+                return time();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Template/NestedSet.php b/lib/Doctrine/TODO/Template/NestedSet.php
new file mode 100644
index 000000000..2d9954c44
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/NestedSet.php
@@ -0,0 +1,52 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_NestedSet
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Roman Borschel <roman@code-factory.org>
+ */
+class Doctrine_Template_NestedSet extends Doctrine_Template
+{
+    private $_options;
+    
+    public function __construct(array $options)
+    {
+        $this->_options = $options;
+    }
+    
+    public function setUp()
+    {
+        $this->_table->setOption('treeOptions', $this->_options);
+        $this->_table->setOption('treeImpl', 'NestedSet');
+    }
+    
+    public function setTableDefinition()
+    {
+        $this->_table->getTree()->setTableDefinition();
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Template/Searchable.php b/lib/Doctrine/TODO/Template/Searchable.php
new file mode 100644
index 000000000..c4054d5de
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/Searchable.php
@@ -0,0 +1,51 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Searchable
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Template_Searchable extends Doctrine_Template
+{     
+    public function __construct(array $options)
+    {
+        $this->_plugin = new Doctrine_Search($options); 
+    }
+    
+    public function setUp()
+    {
+        $this->_plugin->initialize($this->_table);
+
+        $this->addListener(new Doctrine_Search_Listener($this->_plugin));
+    }
+
+    public function batchUpdateIndex($limit = null, $offset = null)
+    {
+        $this->_plugin->batchUpdateIndex($limit, $offset);
+    }
+}
diff --git a/lib/Doctrine/TODO/Template/Sluggable.php b/lib/Doctrine/TODO/Template/Sluggable.php
new file mode 100644
index 000000000..ae6ec1a3f
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/Sluggable.php
@@ -0,0 +1,70 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Sluggable
+ *
+ * Easily create a slug for each record based on a specified set of fields
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Sluggable extends Doctrine_Template
+{
+    /**
+     * Array of timestampable options
+     *
+     * @var string
+     */
+    protected $_options = array('name'    =>  'slug',
+                                'type'    =>  'clob',
+                                'length'  =>  null,
+                                'options' =>  array(),
+                                'fields'  =>  array());
+
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options)
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    /**
+     * setTableDefinition
+     *
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+        $this->hasColumn($this->_options['name'], $this->_options['type'], $this->_options['length'], $this->_options['options']);
+
+        $this->addListener(new Doctrine_Template_Listener_Sluggable($this->_options));
+    }
+}
diff --git a/lib/Doctrine/TODO/Template/Taggable.php b/lib/Doctrine/TODO/Template/Taggable.php
new file mode 100644
index 000000000..2eb475925
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/Taggable.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Taggable
+ *
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @version     $Revision$
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ */
+class Doctrine_Template_Taggable extends Doctrine_Template
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Template/Timestampable.php b/lib/Doctrine/TODO/Template/Timestampable.php
new file mode 100644
index 000000000..3cd4b1775
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/Timestampable.php
@@ -0,0 +1,84 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Timestampable
+ *
+ * Easily add created and updated at timestamps to your doctrine records
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Timestampable extends Doctrine_Template
+{
+    /**
+     * Array of timestampable options
+     *
+     * @var string
+     */
+    protected $_options = array('created' =>  array('name'          =>  'created_at',
+                                                    'type'          =>  'timestamp',
+                                                    'format'        =>  'Y-m-d H:i:s',
+                                                    'disabled'      => false,
+                                                    'expression'    => false,
+                                                    'options'       =>  array()),
+                                'updated' =>  array('name'          =>  'updated_at',
+                                                    'type'          =>  'timestamp',
+                                                    'format'        =>  'Y-m-d H:i:s',
+                                                    'disabled'      => false,
+                                                    'expression'    => false,
+                                                    'onInsert'      => true,
+                                                    'options'       =>  array()));
+
+    /**
+     * __construct
+     *
+     * @param string $array 
+     * @return void
+     */
+    public function __construct(array $options)
+    {
+        $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options);
+    }
+
+    /**
+     * setTableDefinition
+     *
+     * @return void
+     */
+    public function setTableDefinition()
+    {
+        if( ! $this->_options['created']['disabled']) {
+            $this->hasColumn($this->_options['created']['name'], $this->_options['created']['type'], null, $this->_options['created']['options']);
+        }
+
+        if( ! $this->_options['updated']['disabled']) {
+            $this->hasColumn($this->_options['updated']['name'], $this->_options['updated']['type'], null, $this->_options['updated']['options']);
+        }
+
+        $this->addListener(new Doctrine_Template_Listener_Timestampable($this->_options));
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Template/Versionable.php b/lib/Doctrine/TODO/Template/Versionable.php
new file mode 100644
index 000000000..d31a3a3ef
--- /dev/null
+++ b/lib/Doctrine/TODO/Template/Versionable.php
@@ -0,0 +1,52 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Template_Versionable
+ *
+ * @package     Doctrine
+ * @subpackage  Template
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Template_Versionable extends Doctrine_Template
+{
+    public function __construct(array $options)
+    {
+        $this->_plugin = new Doctrine_AuditLog($options);
+    }
+    public function setUp()
+    {
+        $this->_plugin->initialize($this->_table);
+
+        $this->hasColumn('version', 'integer', 8);
+
+        $this->addListener(new Doctrine_AuditLog_Listener($this->_plugin));
+    }
+    public function getAuditLog()
+    {
+        return $this->_plugin;
+    }
+
+}
diff --git a/lib/Doctrine/TODO/Tree/AdjacencyList.php b/lib/Doctrine/TODO/Tree/AdjacencyList.php
new file mode 100644
index 000000000..102c2a84b
--- /dev/null
+++ b/lib/Doctrine/TODO/Tree/AdjacencyList.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: AdjacencyList.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_AdjacencyList
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Tree_AdjacencyList extends Doctrine_Tree implements Doctrine_Tree_Interface
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Tree/Exception.php b/lib/Doctrine/TODO/Tree/Exception.php
new file mode 100644
index 000000000..c510d0c26
--- /dev/null
+++ b/lib/Doctrine/TODO/Tree/Exception.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: Exception.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Tree_Exception extends Doctrine_Exception
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Tree/Interface.php b/lib/Doctrine/TODO/Tree/Interface.php
new file mode 100644
index 000000000..9972e3be5
--- /dev/null
+++ b/lib/Doctrine/TODO/Tree/Interface.php
@@ -0,0 +1,65 @@
+<?php
+/*
+ *  $Id: Interface.php 4364 2008-05-13 21:20:34Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_Interface
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 4364 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+interface Doctrine_Tree_Interface {
+
+    /**
+     * creates root node from given record or from a new record
+     *
+     * @param object $record                    instance of Doctrine_Entity
+     */
+    public function createRoot(Doctrine_Entity $record = null);
+
+    /**
+     * returns root node
+     *
+     * @return object $record                   instance of Doctrine_Entity
+     */
+    public function findRoot($root_id = 1);
+
+    /**
+     * optimised method to returns iterator for traversal of the entire tree from root
+     *
+     * @param array $options                    options
+     * @return object $iterator                 instance of Doctrine_Node_<Implementation>_PreOrderIterator
+     */
+    public function fetchTree($options = array());
+
+    /**
+     * optimised method that returns iterator for traversal of the tree from the given record primary key
+     *
+     * @param mixed $pk                         primary key as used by table::find() to locate node to traverse tree from
+     * @param array $options                    options
+     * @return iterator                         instance of Doctrine_Node_<Implementation>_PreOrderIterator
+     */
+    public function fetchBranch($pk, $options = array());
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Tree/MaterializedPath.php b/lib/Doctrine/TODO/Tree/MaterializedPath.php
new file mode 100644
index 000000000..1b1383731
--- /dev/null
+++ b/lib/Doctrine/TODO/Tree/MaterializedPath.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ *  $Id: MaterializedPath.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_MaterializedPath
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+abstract class Doctrine_Tree_MaterializedPath extends Doctrine_Tree implements Doctrine_Tree_Interface
+{ }
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Tree/NestedSet.php b/lib/Doctrine/TODO/Tree/NestedSet.php
new file mode 100644
index 000000000..b1b69417a
--- /dev/null
+++ b/lib/Doctrine/TODO/Tree/NestedSet.php
@@ -0,0 +1,322 @@
+<?php
+/*
+ *  $Id: NestedSet.php 4364 2008-05-13 21:20:34Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Tree_NestedSet
+ *
+ * @package     Doctrine
+ * @subpackage  Tree
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 4364 $
+ * @author      Joe Simms <joe.simms@websites4.com>
+ */
+class Doctrine_Tree_NestedSet extends Doctrine_Tree implements Doctrine_Tree_Interface
+{
+    private $_baseQuery;
+    private $_baseAlias = "base";
+
+    /**
+     * constructor, creates tree with reference to table and sets default root options
+     *
+     * @param object $table                     instance of Doctrine_Table
+     * @param array $options                    options
+     */
+    public function __construct($table, $options)
+    {
+        // set default many root attributes
+        $options['hasManyRoots'] = isset($options['hasManyRoots']) ? $options['hasManyRoots'] : false;
+        if ($options['hasManyRoots']) {
+            $options['rootColumnName'] = isset($options['rootColumnName']) ? $options['rootColumnName'] : 'root_id';
+        }
+        
+        parent::__construct($table, $options);
+    }
+
+    /**
+     * used to define table attributes required for the NestetSet implementation
+     * adds lft and rgt columns for corresponding left and right values
+     *
+     */
+    public function setTableDefinition()
+    {
+        if ($root = $this->getAttribute('rootColumnName')) {
+            $this->table->setColumn($root, 'integer', 4);
+        }
+
+        $this->table->setColumn('lft', 'integer', 4);
+        $this->table->setColumn('rgt', 'integer', 4);
+        $this->table->setColumn('level', 'integer', 2);
+    }
+
+    /**
+     * creates root node from given record or from a new record
+     *
+     * @param object $record        instance of Doctrine_Entity
+     */
+    public function createRoot(Doctrine_Entity $record = null)
+    {
+        if ( ! $record) {
+            $record = $this->table->create();
+        }
+
+        // if tree is many roots, and no root id has been set, then get next root id
+        if ($root = $this->getAttribute('hasManyRoots') && $record->getNode()->getRootValue() <= 0) {
+            $record->getNode()->setRootValue($this->getNextRootId());
+        }
+
+        $record->set('lft', '1');
+        $record->set('rgt', '2');
+        $record->set('level', 0);
+
+        $record->save();
+
+        return $record;
+    }
+
+    /**
+     * returns root node
+     *
+     * @return object $record        instance of Doctrine_Entity
+     * @deprecated Use fetchRoot()
+     */
+    public function findRoot($rootId = 1)
+    {
+        return $this->fetchRoot($rootId);
+    }
+
+    /**
+     * Fetches a/the root node.
+     *
+     * @param integer $rootId
+     */
+    public function fetchRoot($rootId = 1)
+    {
+        $q = $this->getBaseQuery();
+        $q = $q->addWhere($this->_baseAlias . '.lft = ?', 1);
+        
+        // if tree has many roots, then specify root id
+        $q = $this->returnQueryWithRootId($q, $rootId);
+        $data = $q->execute();
+
+        if (count($data) <= 0) {
+            return false;
+        }
+
+        if ($data instanceof Doctrine_Collection) {
+            $root = $data->getFirst();
+            $root['level'] = 0;
+        } else if (is_array($data)) {
+            $root = array_shift($data);
+            $root['level'] = 0;
+        } else {
+            throw new Doctrine_Tree_Exception("Unexpected data structure returned.");
+        }
+
+        return $root;
+    }
+
+    /**
+     * Fetches a tree.
+     *
+     * @param array $options  Options
+     * @return mixed          The tree or FALSE if the tree could not be found.
+     */
+    public function fetchTree($options = array())
+    {
+        // fetch tree
+        $q = $this->getBaseQuery();
+
+        $q = $q->addWhere($this->_baseAlias . ".lft >= ?", 1);
+
+        // if tree has many roots, then specify root id
+        $rootId = isset($options['root_id']) ? $options['root_id'] : '1';
+        if (is_array($rootId)) {
+            $q->addOrderBy($this->_baseAlias . "." . $this->getAttribute('rootColumnName') .
+                    ", " . $this->_baseAlias . ".lft ASC");
+        } else {
+            $q->addOrderBy($this->_baseAlias . ".lft ASC");
+        }
+        
+        $q = $this->returnQueryWithRootId($q, $rootId);
+        $tree = $q->execute();
+        
+        if (count($tree) <= 0) {
+            return false;
+        }
+        
+        return $tree;
+    }
+
+    /**
+     * Fetches a branch of a tree.
+     *
+     * @param mixed $pk              primary key as used by table::find() to locate node to traverse tree from
+     * @param array $options         Options.
+     * @return mixed                 The branch or FALSE if the branch could not be found.
+     * @todo Only fetch the lft and rgt values of the initial record. more is not needed.
+     */
+    public function fetchBranch($pk, $options = array())
+    {
+        $record = $this->table->find($pk);
+        if ( ! ($record instanceof Doctrine_Entity) || !$record->exists()) {
+            // TODO: if record doesn't exist, throw exception or similar?
+            return false;
+        }
+        //$depth = isset($options['depth']) ? $options['depth'] : null;
+        
+        $q = $this->getBaseQuery();
+        $params = array($record->get('lft'), $record->get('rgt'));
+        $q->addWhere($this->_baseAlias . ".lft >= ? AND " . $this->_baseAlias . ".rgt <= ?", $params)
+                ->addOrderBy($this->_baseAlias . ".lft asc");
+        $q = $this->returnQueryWithRootId($q, $record->getNode()->getRootValue());
+        return $q->execute();
+    }
+
+    /**
+     * Fetches all root nodes. If the tree has only one root this is the same as
+     * fetchRoot().
+     *
+     * @return mixed  The root nodes.
+     */
+    public function fetchRoots()
+    {
+        $q = $this->getBaseQuery();
+        $q = $q->addWhere($this->_baseAlias . '.lft = ?', 1);
+        return $q->execute();
+    }
+
+    /**
+     * calculates the next available root id
+     *
+     * @return integer
+     */
+    public function getNextRootId()
+    {
+        return $this->getMaxRootId() + 1;
+    }
+
+    /**
+     * calculates the current max root id
+     *
+     * @return integer
+     */    
+    public function getMaxRootId()
+    {      
+        $component = $this->table->getComponentName();
+        $column    = $this->getAttribute('rootColumnName');
+
+        // cannot get this dql to work, cannot retrieve result using $coll[0]->max
+        //$dql = "SELECT MAX(c.$column) FROM $component c";
+        
+        $dql = 'SELECT c.' . $column . ' FROM ' . $component . ' c ORDER BY c.' . $column . ' DESC LIMIT 1';
+  
+        $coll = $this->table->getConnection()->query($dql);
+  
+        $max = $coll[0]->get($column);
+  
+        $max = !is_null($max) ? $max : 0;
+  
+        return $max;      
+    }
+
+    /**
+     * returns parsed query with root id where clause added if applicable
+     *
+     * @param object    $query    Doctrine_Query
+     * @param integer   $root_id  id of destination root
+     * @return object   Doctrine_Query
+     */
+    public function returnQueryWithRootId($query, $rootId = 1)
+    {
+        if ($root = $this->getAttribute('rootColumnName')) {
+            if (is_array($rootId)) {
+               $query->addWhere($root . ' IN (' . implode(',', array_fill(0, count($rootId), '?')) . ')',
+                       $rootId);
+            } else {
+               $query->addWhere($root . ' = ?', $rootId); 
+            }
+        }
+
+        return $query;
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @param array $options
+     * @return unknown
+     */
+    public function getBaseQuery()
+    {
+        if ( ! isset($this->_baseQuery)) {
+            $this->_baseQuery = $this->_createBaseQuery();
+        }
+        return $this->_baseQuery->copy();
+    }
+
+    /**
+     * Enter description here...
+     *
+     */
+    public function getBaseAlias()
+    {
+        return $this->_baseAlias;
+    }
+
+    /**
+     * Enter description here...
+     *
+     */
+    private function _createBaseQuery()
+    {
+        $this->_baseAlias = "base";
+        $q = new Doctrine_Query();
+        $q->select($this->_baseAlias . ".*")->from($this->getBaseComponent() . " " . $this->_baseAlias);
+        return $q;
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @param Doctrine_Query $query
+     */
+    public function setBaseQuery(Doctrine_Query $query)
+    {
+        $this->_baseAlias = $query->getRootAlias();
+        $query->addSelect($this->_baseAlias . ".lft, " . $this->_baseAlias . ".rgt, ". $this->_baseAlias . ".level");
+        if ($this->getAttribute('rootColumnName')) {
+            $query->addSelect($this->_baseAlias . "." . $this->getAttribute('rootColumnName'));
+        }
+        $this->_baseQuery = $query;
+    }
+
+    /**
+     * Enter description here...
+     *
+     */
+    public function resetBaseQuery()
+    {
+        $this->_baseQuery = $this->_createBaseQuery();
+    }
+
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Country.php b/lib/Doctrine/TODO/Validator/Country.php
new file mode 100644
index 000000000..664b5ec57
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Country.php
@@ -0,0 +1,302 @@
+<?php
+/*
+ *  $Id: Country.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Country
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Country
+{
+    private static $countries = array(
+        'ad' =>    'Andorra',
+        'ae' =>    'United Arab Emirates',
+        'af' =>    'Afghanistan',
+        'ag' =>    'Antigua and Barbuda',
+        'ai' =>    'Anguilla',
+        'al' =>    'Albania',
+        'am' =>    'Armenia',
+        'an' =>    'Netherlands Antilles',
+        'ao' =>    'Angola',
+        'aq' =>    'Antarctica',
+        'ar' =>    'Argentina',
+        'as' =>    'American Samoa',
+        'at' =>    'Austria',
+        'au' =>    'Australia',
+        'aw' =>    'Aruba',
+        'az' =>    'Azerbaijan',
+        'ba' =>    'Bosnia Hercegovina',
+        'bb' =>    'Barbados',
+        'bd' =>    'Bangladesh',
+        'be' =>    'Belgium',
+        'bf' =>    'Burkina Faso',
+        'bg' =>    'Bulgaria',
+        'bh' =>    'Bahrain',
+        'bi' =>    'Burundi',
+        'bj' =>    'Benin',
+        'bm' =>    'Bermuda',
+        'bn' =>    'Brunei Darussalam',
+        'bo' =>    'Bolivia',
+        'br' =>    'Brazil',
+        'bs' =>    'Bahamas',
+        'bt' =>    'Bhutan',
+        'bv' =>    'Bouvet Island',
+        'bw' =>    'Botswana',
+        'by' =>    'Belarus (Byelorussia)',
+        'bz' =>    'Belize',
+        'ca' =>    'Canada',
+        'cc' =>    'Cocos Islands',
+        'cd' =>    'Congo, The Democratic Republic of the',
+        'cf' =>    'Central African Republic',
+        'cg' =>    'Congo',
+        'ch' =>    'Switzerland',
+        'ci' =>    'Ivory Coast',
+        'ck' =>    'Cook Islands',
+        'cl' =>    'Chile',
+        'cm' =>    'Cameroon',
+        'cn' =>    'China',
+        'co' =>    'Colombia',
+        'cr' =>    'Costa Rica',
+        'cs' =>    'Czechoslovakia',
+        'cu' =>    'Cuba',
+        'cv' =>    'Cape Verde',
+        'cx' =>    'Christmas Island',
+        'cy' =>    'Cyprus',
+        'cz' =>    'Czech Republic',
+        'de' =>    'Germany',
+        'dj' =>    'Djibouti',
+        'dk' =>    'Denmark',
+        'dm' =>    'Dominica',
+        'do' =>    'Dominican Republic',
+        'dz' =>    'Algeria',
+        'ec' =>    'Ecuador',
+        'ee' =>    'Estonia',
+        'eg' =>    'Egypt',
+        'eh' =>    'Western Sahara',
+        'er' =>    'Eritrea',
+        'es' =>    'Spain',
+        'et' =>    'Ethiopia',
+        'fi' =>    'Finland',
+        'fj' =>    'Fiji',
+        'fk' =>    'Falkland Islands',
+        'fm' =>    'Micronesia',
+        'fo' =>    'Faroe Islands',
+        'fr' =>    'France',
+        'fx' =>    'France, Metropolitan FX',
+        'ga' =>    'Gabon',
+        'gb' =>    'United Kingdom (Great Britain)',
+        'gd' =>    'Grenada',
+        'ge' =>    'Georgia',
+        'gf' =>    'French Guiana',
+        'gh' =>    'Ghana',
+        'gi' =>    'Gibraltar',
+        'gl' =>    'Greenland',
+        'gm' =>    'Gambia',
+        'gn' =>    'Guinea',
+        'gp' =>    'Guadeloupe',
+        'gq' =>    'Equatorial Guinea',
+        'gr' =>    'Greece',
+        'gs' =>    'South Georgia and the South Sandwich Islands',
+        'gt' =>    'Guatemala',
+        'gu' =>    'Guam',
+        'gw' =>    'Guinea-bissau',
+        'gy' =>    'Guyana',
+        'hk' =>    'Hong Kong',
+        'hm' =>    'Heard and McDonald Islands',
+        'hn' =>    'Honduras',
+        'hr' =>    'Croatia',
+        'ht' =>    'Haiti',
+        'hu' =>    'Hungary',
+        'id' =>    'Indonesia',
+        'ie' =>    'Ireland',
+        'il' =>    'Israel',
+        'in' =>    'India',
+        'io' =>    'British Indian Ocean Territory',
+        'iq' =>    'Iraq',
+        'ir' =>    'Iran',
+        'is' =>    'Iceland',
+        'it' =>    'Italy',
+        'jm' =>    'Jamaica',
+        'jo' =>    'Jordan',
+        'jp' =>    'Japan',
+        'ke' =>    'Kenya',
+        'kg' =>    'Kyrgyzstan',
+        'kh' =>    'Cambodia',
+        'ki' =>    'Kiribati',
+        'km' =>    'Comoros',
+        'kn' =>    'Saint Kitts and Nevis',
+        'kp' =>    'North Korea',
+        'kr' =>    'South Korea',
+        'kw' =>    'Kuwait',
+        'ky' =>    'Cayman Islands',
+        'kz' =>    'Kazakhstan',
+        'la' =>    'Laos',
+        'lb' =>    'Lebanon',
+        'lc' =>    'Saint Lucia',
+        'li' =>    'Lichtenstein',
+        'lk' =>    'Sri Lanka',
+        'lr' =>    'Liberia',
+        'ls' =>    'Lesotho',
+        'lt' =>    'Lithuania',
+        'lu' =>    'Luxembourg',
+        'lv' =>    'Latvia',
+        'ly' =>    'Libya',
+        'ma' =>    'Morocco',
+        'mc' =>    'Monaco',
+        'md' =>    'Moldova Republic',
+        'mg' =>    'Madagascar',
+        'mh' =>    'Marshall Islands',
+        'mk' =>    'Macedonia, The Former Yugoslav Republic of',
+        'ml' =>    'Mali',
+        'mm' =>    'Myanmar',
+        'mn' =>    'Mongolia',
+        'mo' =>    'Macau',
+        'mp' =>    'Northern Mariana Islands',
+        'mq' =>    'Martinique',
+        'mr' =>    'Mauritania',
+        'ms' =>    'Montserrat',
+        'mt' =>    'Malta',
+        'mu' =>    'Mauritius',
+        'mv' =>    'Maldives',
+        'mw' =>    'Malawi',
+        'mx' =>    'Mexico',
+        'my' =>    'Malaysia',
+        'mz' =>    'Mozambique',
+        'na' =>    'Namibia',
+        'nc' =>    'New Caledonia',
+        'ne' =>    'Niger',
+        'nf' =>    'Norfolk Island',
+        'ng' =>    'Nigeria',
+        'ni' =>    'Nicaragua',
+        'nl' =>    'Netherlands',
+        'no' =>    'Norway',
+        'np' =>    'Nepal',
+        'nr' =>    'Nauru',
+        'nt' =>    'Neutral Zone',
+        'nu' =>    'Niue',
+        'nz' =>    'New Zealand',
+        'om' =>    'Oman',
+        'pa' =>    'Panama',
+        'pe' =>    'Peru',
+        'pf' =>    'French Polynesia',
+        'pg' =>    'Papua New Guinea',
+        'ph' =>    'Philippines',
+        'pk' =>    'Pakistan',
+        'pl' =>    'Poland',
+        'pm' =>    'St. Pierre and Miquelon',
+        'pn' =>    'Pitcairn',
+        'pr' =>    'Puerto Rico',
+        'pt' =>    'Portugal',
+        'pw' =>    'Palau',
+        'py' =>    'Paraguay',
+        'qa' =>    'Qatar',
+        're' =>    'Reunion',
+        'ro' =>    'Romania',
+        'ru' =>    'Russia',
+        'rw' =>    'Rwanda',
+        'sa' =>    'Saudi Arabia',
+        'sb' =>    'Solomon Islands',
+        'sc' =>    'Seychelles',
+        'sd' =>    'Sudan',
+        'se' =>    'Sweden',
+        'sg' =>    'Singapore',
+        'sh' =>    'St. Helena',
+        'si' =>    'Slovenia',
+        'sj' =>    'Svalbard and Jan Mayen Islands',
+        'sk' =>    'Slovakia (Slovak Republic)',
+        'sl' =>    'Sierra Leone',
+        'sm' =>    'San Marino',
+        'sn' =>    'Senegal',
+        'so' =>    'Somalia',
+        'sr' =>    'Suriname',
+        'st' =>    'Sao Tome and Principe',
+        'sv' =>    'El Salvador',
+        'sy' =>    'Syria',
+        'sz' =>    'Swaziland',
+        'tc' =>    'Turks and Caicos Islands',
+        'td' =>    'Chad',
+        'tf' =>    'French Southern Territories',
+        'tg' =>    'Togo',
+        'th' =>    'Thailand',
+        'tj' =>    'Tajikistan',
+        'tk' =>    'Tokelau',
+        'tm' =>    'Turkmenistan',
+        'tn' =>    'Tunisia',
+        'to' =>    'Tonga',
+        'tp' =>    'East Timor',
+        'tr' =>    'Turkey',
+        'tt' =>    'Trinidad, Tobago',
+        'tv' =>    'Tuvalu',
+        'tw' =>    'Taiwan',
+        'tz' =>    'Tanzania',
+        'ua' =>    'Ukraine',
+        'ug' =>    'Uganda',
+        'uk' =>    'United Kingdom',
+        'um' =>    'United States Minor Islands',
+        'us' =>    'United States of America',
+        'uy' =>    'Uruguay',
+        'uz' =>    'Uzbekistan',
+        'va' =>    'Vatican City',
+        'vc' =>    'Saint Vincent, Grenadines',
+        've' =>    'Venezuela',
+        'vg' =>    'Virgin Islands (British)',
+        'vi' =>    'Virgin Islands (USA)',
+        'vn' =>    'Viet Nam',
+        'vu' =>    'Vanuatu',
+        'wf' =>    'Wallis and Futuna Islands',
+        'ws' =>    'Samoa',
+        'ye' =>    'Yemen',
+        'yt' =>    'Mayotte',
+        'yu' =>    'Yugoslavia',
+        'za' =>    'South Africa',
+        'zm' =>    'Zambia',
+        'zr' =>    'Zaire',
+        'zw' =>    'Zimbabwe');
+
+    /**
+     * returns all available country codes
+     *
+     * @return array
+     */
+    public static function getCountries()
+    {
+        return self::$countries;
+    }
+
+    /**
+     * checks if given value is a valid country code
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        $value = strtolower($value);
+
+        return isset(self::$countries[$value]);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Creditcard.php b/lib/Doctrine/TODO/Validator/Creditcard.php
new file mode 100644
index 000000000..90e2f7a6d
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Creditcard.php
@@ -0,0 +1,47 @@
+<?php
+/*
+ *  $Id: Creditcard.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Creditcard
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Creditcard
+{                                                         
+    /**
+     * checks if given value is a valid credit card number
+     *
+     * @link http://www.owasp.org/index.php/OWASP_Validation_Regex_Repository
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        return preg_match('#^((4\d{3})|(5[1-5]\d{2})|(6011)|(7\d{3}))-?\d{4}-?\d{4}-?\d{4}|3[4,7]\d{13}$#', $value);
+    }
+
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Date.php b/lib/Doctrine/TODO/Validator/Date.php
new file mode 100644
index 000000000..289d5257a
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Date.php
@@ -0,0 +1,53 @@
+<?php
+/*
+ *  $Id: Date.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Date
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Date
+{
+    /**
+     * checks if given value is a valid date
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if ($value === null) {
+            return true;
+        }
+        $e = explode('-', $value);
+
+        if (count($e) !== 3) {
+            return false;
+        }
+        return checkdate($e[1], $e[2], $e[0]);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Driver.php b/lib/Doctrine/TODO/Validator/Driver.php
new file mode 100644
index 000000000..3093f8320
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Driver.php
@@ -0,0 +1,116 @@
+<?php
+/*
+ *  $Id: Notnull.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Driver
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Driver
+{
+    /**
+     * @var array $_args     an array of plugin specific args
+     */
+    protected $_args = array();
+
+    /**
+     * __get
+     * an alias for getOption
+     *
+     * @param string $arg
+     */
+    public function __get($arg)
+    {
+        if (isset($this->_args[$arg])) {
+            return $this->_args[$arg];
+        }
+        return null;
+    }
+
+    /**
+     * __isset
+     *
+     * @param string $arg
+     */
+    public function __isset($arg)
+    {
+        return isset($this->_args[$arg]);
+    }
+
+    /**
+     * sets given value to an argument
+     *
+     * @param $arg          the name of the option to be changed
+     * @param $value        the value of the option
+     * @return Doctrine_Validator_Driver    this object
+     */
+    public function __set($arg, $value)
+    {
+        $this->_args[$arg] = $value;
+        
+        return $this;
+    }
+
+    /**
+     * returns the value of an argument
+     *
+     * @param $arg          the name of the option to retrieve
+     * @return mixed        the value of the option
+     */
+    public function getArg($arg)
+    {
+        if ( ! isset($this->_args[$arg])) {
+            throw new Doctrine_Plugin_Exception('Unknown option ' . $arg);
+        }
+        
+        return $this->_args[$arg];
+    }
+
+    /**
+     * sets given value to an argument
+     *
+     * @param $arg          the name of the option to be changed
+     * @param $value        the value of the option
+     * @return Doctrine_Validator_Driver    this object
+     */
+    public function setArg($arg, $value)
+    {
+        $this->_args[$arg] = $value;
+        
+        return $this;
+    }
+
+    /**
+     * returns all args and their associated values
+     *
+     * @return array    all args as an associative array
+     */
+    public function getArgs()
+    {
+        return $this->_args;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Email.php b/lib/Doctrine/TODO/Validator/Email.php
new file mode 100644
index 000000000..411e3e8fd
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Email.php
@@ -0,0 +1,78 @@
+<?php
+/*
+ *  $Id: Email.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Email
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Email
+{
+    /**
+     * checks if given value is a valid email address
+     *
+     * @link http://iamcal.com/publish/articles/php/parsing_email/pdf/
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if ($value === null) {
+            return true;
+        }
+        if (isset($this->args)) {
+            $parts = explode('@', $value);
+            if (isset($parts[1]) && function_exists('checkdnsrr')) {
+                if ( ! checkdnsrr($parts[1], 'MX')) {
+                    return false;
+                }
+            }
+        }
+
+        $qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
+        $dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
+        $atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
+        $quotedPair = '\\x5c[\\x00-\\x7f]';
+        $domainLiteral = "\\x5b($dtext|$quotedPair)*\\x5d";
+        $quotedString = "\\x22($qtext|$quotedPair)*\\x22";
+        $domain_ref = $atom;
+        $subDomain = "($domain_ref|$domainLiteral)";
+        $word = "($atom|$quotedString)";
+        $domain = "$subDomain(\\x2e$subDomain)+";
+        /*
+          following pseudocode to allow strict checking - ask pookey about this if you're puzzled
+
+          if ($this->getValidationOption('strict_checking') == true) {
+              $domain = "$sub_domain(\\x2e$sub_domain)*";
+          }
+        */
+        $localPart = "$word(\\x2e$word)*";
+        $addrSpec = "$localPart\\x40$domain";
+
+        return (bool) preg_match("!^$addrSpec$!D", $value);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/ErrorStack.php b/lib/Doctrine/TODO/Validator/ErrorStack.php
new file mode 100644
index 000000000..a2d04acd8
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/ErrorStack.php
@@ -0,0 +1,149 @@
+<?php
+/*
+ *  $Id: ErrorStack.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_ErrorStack
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @author      Roman Borschel <roman@code-factory.org>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ */
+class Doctrine_Validator_ErrorStack extends Doctrine_Access implements Countable, IteratorAggregate
+{
+
+    /**
+     * The errors of the error stack.
+     *
+     * @var array
+     */
+    protected $errors = array();
+
+    protected $classname = "";
+
+    /**
+     * Constructor
+     *
+     */
+    public function __construct($classname = "")
+    {
+        $this->classname = $classname;
+    }
+
+    /**
+     * Adds an error to the stack.
+     *
+     * @param string $invalidFieldName
+     * @param string $errorType
+     */
+    public function add($invalidFieldName, $errorCode = 'general')
+    {
+        $this->errors[$invalidFieldName][] = $errorCode;
+    }
+
+    /**
+     * Removes all existing errors for the specified field from the stack.
+     *
+     * @param string $fieldName
+     */
+    public function remove($fieldName)
+    {
+        if (isset($this->errors[$fieldName])) {
+            unset($this->errors[$fieldName]);
+        }
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @param unknown_type $name
+     * @return unknown
+     */
+    public function get($fieldName)
+    {
+        return isset($this->errors[$fieldName]) ? $this->errors[$fieldName] : null;
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @param unknown_type $name
+     */
+    public function set($fieldName, $errorCode)
+    {
+        $this->add($fieldName, $errorCode);
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @return unknown
+     */
+    public function contains($fieldName)
+    {
+        return array_key_exists($fieldName, $this->errors);
+    }
+
+    /**
+     * Removes all errors from the stack.
+     */
+    public function clear()
+    {
+        $this->errors = array();
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @return unknown
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->errors);
+    }
+
+    public function toArray()
+    {
+        return $this->errors;	
+    }
+
+    /**
+     * Enter description here...
+     *
+     * @return unknown
+     */
+    public function count()
+    {
+        return count($this->errors);
+    }
+
+    /**
+     * Get the classname where the errors occured
+     *
+     */
+    public function getClassname(){
+        return $this->classname;
+    }
+}
diff --git a/lib/Doctrine/TODO/Validator/Exception.php b/lib/Doctrine/TODO/Validator/Exception.php
new file mode 100644
index 000000000..2fffea53c
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Exception.php
@@ -0,0 +1,100 @@
+<?php
+/*
+ *  $Id: Exception.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+Doctrine::autoload('Doctrine_Exception');
+/**
+ * Doctrine_Validator_Exception
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ */
+class Doctrine_Validator_Exception extends Doctrine_Exception implements Countable, IteratorAggregate
+{
+    /**
+     * @var array $invalid
+     */
+    private $invalid = array();
+
+    /**
+     * @param Doctrine_Validator $validator
+     */
+    public function __construct(array $invalid)
+    {
+        $this->invalid = $invalid;
+        parent::__construct($this->generateMessage());
+    }
+
+    public function getInvalidRecords()
+    {
+        return $this->invalid;
+    }
+
+    public function getIterator()
+    {
+        return new ArrayIterator($this->invalid);
+    }
+
+    public function count()
+    {
+        return count($this->invalid);
+    }
+
+    /**
+     * __toString
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+
+        return parent::__toString();
+    }
+
+    /**
+     * Generate a message with all classes that have exceptions
+     */
+    private function generateMessage()
+    {
+        $message = "";
+        foreach ($this->invalid as $record) {
+           $message .= "Validaton error in class " . get_class($record) . " ";
+        }
+        return $message;
+    }
+
+    /**
+     * This method will apply the value of the $function variable as a user_func 
+     * to tall errorstack objects in the exception
+     *
+     * @param mixed Either string with function name or array with object, 
+     * functionname. See call_user_func in php manual for more inforamtion
+     */
+    public function inspect($function)
+    {
+        foreach ($this->invalid as $record) {
+            call_user_func($function, $record->getErrorStack());
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Future.php b/lib/Doctrine/TODO/Validator/Future.php
new file mode 100644
index 000000000..7eac4066d
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Future.php
@@ -0,0 +1,79 @@
+<?php
+/*
+ *  $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Future
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Roman Borschel <roman@code-factory.org>
+ */
+class Doctrine_Validator_Future
+{
+    /**
+     * checks if the given value is a valid date in the future.
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if ($value === null) {
+            return true;
+        }
+        $e = explode('-', $value);
+
+        if (count($e) !== 3) {
+            return false;
+        }
+        
+        if (is_array($this->args) && isset($this->args['timezone'])) {
+            switch (strtolower($this->args['timezone'])) {
+                case 'gmt':
+                    $now = gmdate("U") - date("Z");
+                    break;
+                default:
+                    $now = getdate();
+                    break;
+            }
+        } else {
+            $now = getdate();
+        }
+        
+        if ($now['year'] > $e[0]) {
+            return false;
+        } else if ($now['year'] == $e[0]) {
+            if ($now['mon'] > $e[1]) {
+                return false;
+            } else if ($now['mon'] == $e[1]) {
+                return $now['mday'] < $e[2];
+            } else {
+                return true;
+            }
+        } else {
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Htmlcolor.php b/lib/Doctrine/TODO/Validator/Htmlcolor.php
new file mode 100644
index 000000000..117142aa5
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Htmlcolor.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ *  $Id: Htmlcolor.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_HtmlColor
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_HtmlColor
+{
+    /**
+     * checks if given value is a valid html color code
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if ( ! preg_match("/^#{0,1}[0-9]{6}$/", $value)) {
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Ip.php b/lib/Doctrine/TODO/Validator/Ip.php
new file mode 100644
index 000000000..b7d09f568
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Ip.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: Ip.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Ip
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Ip
+{
+    /**
+     * checks if given value is valid ip address
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        return (bool) ip2long(str_replace("\0", '', $value));
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Minlength.php b/lib/Doctrine/TODO/Validator/Minlength.php
new file mode 100644
index 000000000..62d69f167
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Minlength.php
@@ -0,0 +1,49 @@
+<?php
+/*
+ *  $Id: Minlength.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Regexp
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Gijs van Dulmen <gijs@vandulmen.net>
+ */
+class Doctrine_Validator_Minlength 
+{
+    /**
+     * checks if given value is more length than the minimum length required
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (isset($this->args) && strlen($value) < $this->args) {
+            return false;
+        }
+
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Nospace.php b/lib/Doctrine/TODO/Validator/Nospace.php
new file mode 100644
index 000000000..cf735d8dd
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Nospace.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: Nospace.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Nospace
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Nospace extends Doctrine_Validator_Driver
+{
+    /**
+     * checks that value doesn't contain any space chars
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        return ($value === null || ! preg_match('/\s/', $value));
+    }
+}
diff --git a/lib/Doctrine/TODO/Validator/Notblank.php b/lib/Doctrine/TODO/Validator/Notblank.php
new file mode 100644
index 000000000..092aec992
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Notblank.php
@@ -0,0 +1,46 @@
+<?php
+/*
+ *  $Id: Notblank.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Notblank
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Notblank extends Doctrine_Validator_Driver
+{
+    /**
+     * checks that value isn't blank
+     * a value is blank when its either null or contains only space characters
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        return (trim($value) !== '' && $value !== null);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Notnull.php b/lib/Doctrine/TODO/Validator/Notnull.php
new file mode 100644
index 000000000..dee5bcf8c
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Notnull.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *  $Id: Notnull.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Notnull
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Notnull extends Doctrine_Validator_Driver
+{
+    /**
+     * checks that given value isn't null
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        return ($value !== null);
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Past.php b/lib/Doctrine/TODO/Validator/Past.php
new file mode 100644
index 000000000..53a277bc9
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Past.php
@@ -0,0 +1,79 @@
+<?php
+/*
+ *  $Id: Date.php 2367 2007-09-02 20:00:27Z zYne $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Past
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision$
+ * @author      Roman Borschel <roman@code-factory.org>
+ */
+class Doctrine_Validator_Past
+{
+    /**
+     * checks if the given value is a valid date in the past.
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if ($value === null) {
+            return true;
+        }
+        $e = explode('-', $value);
+
+        if (count($e) !== 3) {
+            return false;
+        }
+        
+        if (is_array($this->args) && isset($this->args['timezone'])) {
+            switch (strtolower($this->args['timezone'])) {
+                case 'gmt':
+                    $now = gmdate("U") - date("Z");
+                    break;
+                default:
+                    $now = getdate();
+                    break;
+            }
+        } else {
+            $now = getdate();
+        }
+        
+        if ($now['year'] < $e[0]) {
+            return false;
+        } else if ($now['year'] == $e[0]) {
+            if ($now['mon'] < $e[1]) {
+                return false;
+            } else if ($now['mon'] == $e[1]) {
+                return $now['mday'] > $e[2];
+            } else {
+                return true;
+            }
+        } else {
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Protected.php b/lib/Doctrine/TODO/Validator/Protected.php
new file mode 100644
index 000000000..6fd199e66
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Protected.php
@@ -0,0 +1 @@
+<?php
diff --git a/lib/Doctrine/TODO/Validator/Range.php b/lib/Doctrine/TODO/Validator/Range.php
new file mode 100644
index 000000000..20424d36b
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Range.php
@@ -0,0 +1,51 @@
+<?php
+/*
+ *  $Id: Range.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Range
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Range
+{
+    /**
+     * checks if value is within given range
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if (isset($this->args[0]) && $value < $this->args[0]) {
+            return false;
+        }
+        if (isset($this->args[1]) && $value > $this->args[1]) {
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Readonly.php b/lib/Doctrine/TODO/Validator/Readonly.php
new file mode 100644
index 000000000..51caaf4ca
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Readonly.php
@@ -0,0 +1,43 @@
+<?php
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Readonly
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @author      Adam Huttler <ahuttler@geminisbs.com>
+ */
+class Doctrine_Validator_Readonly
+{
+    /**
+     * checks if value has been modified
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        $modified = $this->invoker->getModified();
+        
+        return array_key_exists($this->field, $modified) ? false : true;
+    }
+}
diff --git a/lib/Doctrine/TODO/Validator/Regexp.php b/lib/Doctrine/TODO/Validator/Regexp.php
new file mode 100644
index 000000000..0ab524d63
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Regexp.php
@@ -0,0 +1,62 @@
+<?php
+/*
+ *  $Id: Regexp.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Regexp
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Regexp
+{
+    /**
+     * checks if given value satisfies a regular expression
+     *
+     * @param mixed $value
+     * @param mixed $args
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if ( ! isset($this->args)) {
+           return true;
+        }
+        if (is_array($this->args)) {
+            foreach ($this->args as $regexp) {
+                if ( ! preg_match($regexp, $value)) {
+                    return false;
+                }
+            }
+            return true;
+        } else {
+            if (preg_match($this->args, $value)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Time.php b/lib/Doctrine/TODO/Validator/Time.php
new file mode 100644
index 000000000..1f9fd4115
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Time.php
@@ -0,0 +1,62 @@
+<?php
+/*
+ *  $Id: Time.php 3884 2008-02-22 18:26:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Time
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3884 $
+ * @author      Mark Pearson <mark.pearson0@googlemail.com>
+ */
+class Doctrine_Validator_Time
+{
+    /**
+     * checks if given value is a valid time
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if ($value === null) {
+            return true;
+        }
+        $e = explode(':', $value);
+
+        if (count($e) !== 3) {
+            return false;
+        }
+        
+        if (!preg_match('/^ *[0-9]{2}:[0-9]{2}:[0-9]{2} *$/', $value)) {
+            return false;
+        }
+        
+        $hr = intval($e[0], 10);
+        $min = intval($e[1], 10);
+        $sec = intval($e[2], 10);
+        
+        return $hr >= 0 && $hr <= 23 && $min >= 0 && $min <= 59 && $sec >= 0 && $sec <= 59;      
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Timestamp.php b/lib/Doctrine/TODO/Validator/Timestamp.php
new file mode 100644
index 000000000..a5ca739e4
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Timestamp.php
@@ -0,0 +1,66 @@
+<?php
+/*
+ *  $Id: Timestamp.php 3884 2008-02-22 18:26:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Timestamp
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3884 $
+ * @author      Mark Pearson <mark.pearson0@googlemail.com>
+ */
+class Doctrine_Validator_Timestamp
+{
+    /**
+     * checks if given value is a valid timestamp (YYYY-MM-DD HH:MM:SS)
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        if ($value === null) {
+            return true;
+        }
+
+        if (!preg_match('/^ *[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} *$/', $value)) {
+            return false;
+        }
+        
+        list($date, $time) = explode(' ', trim($value));
+        
+        $dateValidator = Doctrine_Validator::getValidator('date');
+        $timeValidator = Doctrine_Validator::getValidator('time');
+        
+        if (!$dateValidator->validate($date)) {
+            return false;
+        }
+        
+        if (!$timeValidator->validate($time)) {
+            return false;
+        } 
+
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Unique.php b/lib/Doctrine/TODO/Validator/Unique.php
new file mode 100644
index 000000000..aa861336e
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Unique.php
@@ -0,0 +1,71 @@
+<?php
+/*
+ *  $Id: Unique.php 4364 2008-05-13 21:20:34Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Unique
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 4364 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Unique
+{
+    /**
+     * checks if given value is unique
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        $table = $this->invoker->getTable();
+        $pks = (array)$table->getIdentifier();
+
+        if ( is_array($pks) ) {
+            $pks = join(',', $pks);
+        }
+
+        $sql   = 'SELECT ' . $pks . ' FROM ' . $table->getTableName() . ' WHERE ' . $this->field . ' = ?';
+        
+        $values = array();
+        $values[] = $value;
+        
+        // If the record is not new we need to add primary key checks because its ok if the 
+        // unique value already exists in the database IF the record in the database is the same
+        // as the one that is validated here.
+        $state = $this->invoker->state();
+        if ( ! ($state == Doctrine_Entity::STATE_TDIRTY || $state == Doctrine_Entity::STATE_TCLEAN)) {
+            foreach ((array) $table->getIdentifier() as $pk) {
+                $sql .= " AND {$pk} != ?";
+                $values[] = $this->invoker->$pk;
+            }
+        }
+        
+        $stmt  = $table->getConnection()->getDbh()->prepare($sql);
+        $stmt->execute($values);
+
+        return ( ! is_array($stmt->fetch()));
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Unsigned.php b/lib/Doctrine/TODO/Validator/Unsigned.php
new file mode 100644
index 000000000..02af1fd37
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Unsigned.php
@@ -0,0 +1,50 @@
+<?php
+/*
+ *  $Id: Enum.php 1080 2007-02-10 18:17:08Z romanb $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Unsigned
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 1080 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Unsigned
+{
+    /**
+     * checks if given value is a valid unsigned integer
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        $int = (int) $value;
+
+        if ($int != $value || $int < 0) {
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/lib/Doctrine/TODO/Validator/Usstate.php b/lib/Doctrine/TODO/Validator/Usstate.php
new file mode 100644
index 000000000..b5dbc50d5
--- /dev/null
+++ b/lib/Doctrine/TODO/Validator/Usstate.php
@@ -0,0 +1,105 @@
+<?php
+/*
+ *  $Id: Usstate.php 3882 2008-02-22 18:11:35Z jwage $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.phpdoctrine.org>.
+ */
+
+/**
+ * Doctrine_Validator_Usstate
+ *
+ * @package     Doctrine
+ * @subpackage  Validator
+ * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link        www.phpdoctrine.org
+ * @since       1.0
+ * @version     $Revision: 3882 $
+ * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
+ */
+class Doctrine_Validator_Usstate
+{
+    private static $states = array(
+                'AK' => true,
+                'AL' => true,
+                'AR' => true,
+                'AZ' => true,
+                'CA' => true,
+                'CO' => true,
+                'CT' => true,
+                'DC' => true,
+                'DE' => true,
+                'FL' => true,
+                'GA' => true,
+                'HI' => true,
+                'IA' => true,
+                'ID' => true,
+                'IL' => true,
+                'IN' => true,
+                'KS' => true,
+                'KY' => true,
+                'LA' => true,
+                'MA' => true,
+                'MD' => true,
+                'ME' => true,
+                'MI' => true,
+                'MN' => true,
+                'MO' => true,
+                'MS' => true,
+                'MT' => true,
+                'NC' => true,
+                'ND' => true,
+                'NE' => true,
+                'NH' => true,
+                'NJ' => true,
+                'NM' => true,
+                'NV' => true,
+                'NY' => true,
+                'OH' => true,
+                'OK' => true,
+                'OR' => true,
+                'PA' => true,
+                'PR' => true,
+                'RI' => true,
+                'SC' => true,
+                'SD' => true,
+                'TN' => true,
+                'TX' => true,
+                'UT' => true,
+                'VA' => true,
+                'VI' => true,
+                'VT' => true,
+                'WA' => true,
+                'WI' => true,
+                'WV' => true,
+                'WY' => true
+            );
+    public function getStates()
+    {
+        return self::$states;
+    }
+
+    /**
+     * checks if given value is a valid US state code
+     *
+     * @param string $args
+     * @return boolean
+     */
+    public function validate($value)
+    {
+        return isset(self::$states[$value]);
+    }
+}
\ No newline at end of file