protected static function buildPointers(MetaClass $class)
    {
        $out = null;
        if (!$class->getPattern() instanceof AbstractClassPattern) {
            if ($source = $class->getSourceLink()) {
                $out .= <<<EOT
\tprotected \$linkName =  '{$source}';
\t

EOT;
            }
            if ($class->getIdentifier()->getColumnName() !== 'id') {
                $out .= <<<EOT
public function getIdName()
{
\treturn '{$class->getIdentifier()->getColumnName()}';
}

EOT;
            }
            $out .= <<<EOT
public function getTable()
{
\treturn '{$class->getTableName()}';
}

public function getObjectName()
{
\treturn '{$class->getName()}';
}

public function getSequence()
{
\treturn '{$class->getTableName()}_id';
}
EOT;
        } elseif ($class->getWithInternalProperties()) {
            $out .= <<<EOT
// no get{Table,ObjectName,Sequence} for abstract class
EOT;
        }
        if ($liaisons = $class->getReferencingClasses()) {
            $uncachers = array();
            foreach ($liaisons as $className) {
                $uncachers[] = $className . '::dao()->uncacheLists();';
            }
            $uncachers = implode("\n", $uncachers);
            $out .= <<<EOT


public function uncacheLists()
{
{$uncachers}

return parent::uncacheLists();
}
EOT;
        }
        return $out;
    }
    public static function buildContainer(MetaClass $class, MetaClassProperty $holder)
    {
        $out = self::getHead();
        $containerName = $class->getName() . ucfirst($holder->getName()) . 'DAO';
        $out .= 'final class ' . $containerName . ' extends ' . $holder->getRelation()->toString() . 'Linked' . "\n{\n";
        $className = $class->getName();
        $propertyName = strtolower($className[0]) . substr($className, 1);
        $remoteColumnName = $holder->getType()->getClass()->getTableName();
        $out .= <<<EOT
public function __construct({$className} \${$propertyName}, \$lazy = false)
{
\tparent::__construct(
\t\t\${$propertyName},
\t\t{$holder->getType()->getClassName()}::dao(),
\t\t\$lazy
\t);
}

/**
 * @return {$containerName}
**/
public static function create({$className} \${$propertyName}, \$lazy = false)
{
\treturn new self(\${$propertyName}, \$lazy);
}

EOT;
        if ($holder->getRelation()->getId() == MetaRelation::MANY_TO_MANY) {
            $out .= <<<EOT

public function getHelperTable()
{
\treturn '{$class->getTableName()}_{$remoteColumnName}';
}

public function getChildIdField()
{
\treturn '{$remoteColumnName}_id';
}

EOT;
        }
        $out .= <<<EOT

public function getParentIdField()
{
\treturn '{$class->getTableName()}_id';
}

EOT;
        $out .= "}\n";
        $out .= self::getHeel();
        return $out;
    }
    public static function buildRelations(MetaClass $class)
    {
        $out = null;
        $knownJunctions = array();
        foreach ($class->getAllProperties() as $property) {
            if ($relation = $property->getRelation()) {
                $foreignClass = $property->getType()->getClass();
                if ($relation->getId() == MetaRelation::ONE_TO_MANY || !$foreignClass->getPattern()->tableExists() || $class->getParent()) {
                    continue;
                } elseif ($relation->getId() == MetaRelation::MANY_TO_MANY) {
                    $tableName = $class->getTableName() . '_' . $foreignClass->getTableName();
                    if (isset($knownJunctions[$tableName])) {
                        continue;
                    } else {
                        $knownJunctions[$tableName] = true;
                    }
                    $foreignPropery = clone $foreignClass->getIdentifier();
                    $name = $class->getName();
                    $name = strtolower($name[0]) . substr($name, 1);
                    $name .= 'Id';
                    $foreignPropery->setName($name)->setColumnName($foreignPropery->getConvertedName())->setIdentifier(false);
                    // we don't want any garbage in such tables
                    $property = clone $property;
                    $property->required();
                    // prevent name collisions
                    if ($property->getRelationColumnName() == $foreignPropery->getColumnName()) {
                        $foreignPropery->setColumnName($class->getTableName() . '_' . $property->getConvertedName() . '_id');
                    }
                    $out .= <<<EOT
\$schema->
\taddTable(
\t\tDBTable::create('{$tableName}')->
\t\t{$property->toColumn()}->
\t\t{$foreignPropery->toColumn()}->
\t\taddUniques('{$property->getRelationColumnName()}', '{$foreignPropery->getColumnName()}')
\t);


EOT;
                } else {
                    $sourceTable = $class->getTableName();
                    $sourceColumn = $property->getRelationColumnName();
                    $targetTable = $foreignClass->getTableName();
                    $targetColumn = $foreignClass->getIdentifier()->getColumnName();
                    $out .= <<<EOT
// {$sourceTable}.{$sourceColumn} -> {$targetTable}.{$targetColumn}
\$schema->
\tgetTableByName('{$sourceTable}')->
\t\tgetColumnByName('{$sourceColumn}')->
\t\t\tsetReference(
\t\t\t\t\$schema->
\t\t\t\t\tgetTableByName('{$targetTable}')->
\t\t\t\t\tgetColumnByName('{$targetColumn}'),
\t\t\t\tForeignChangeAction::restrict(),
\t\t\t\tForeignChangeAction::cascade()
\t\t\t);


EOT;
                }
            }
        }
        return $out;
    }