Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / orm / lib / Doctrine / ORM / Mapping / Driver / AnnotationDriver.php
1 <?php
2 /*
3  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14  *
15  * This software consists of voluntary contributions made by many individuals
16  * and is licensed under the MIT license. For more information, see
17  * <http://www.doctrine-project.org>.
18  */
19
20 namespace Doctrine\ORM\Mapping\Driver;
21
22 use Doctrine\Common\Annotations\AnnotationReader,
23     Doctrine\ORM\Mapping\MappingException,
24     Doctrine\ORM\Mapping\JoinColumn,
25     Doctrine\ORM\Mapping\Column,
26     Doctrine\Common\Persistence\Mapping\ClassMetadata,
27     Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver;
28
29 /**
30  * The AnnotationDriver reads the mapping metadata from docblock annotations.
31  *
32  * @since 2.0
33  * @author Benjamin Eberlei <kontakt@beberlei.de>
34  * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
35  * @author Jonathan H. Wage <jonwage@gmail.com>
36  * @author Roman Borschel <roman@code-factory.org>
37  */
38 class AnnotationDriver extends AbstractAnnotationDriver
39 {
40     /**
41      * {@inheritDoc}
42      */
43     protected $entityAnnotationClasses = array(
44         'Doctrine\ORM\Mapping\Entity' => 1,
45         'Doctrine\ORM\Mapping\MappedSuperclass' => 2,
46     );
47
48     /**
49      * {@inheritDoc}
50      */
51     public function loadMetadataForClass($className, ClassMetadata $metadata)
52     {
53         /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
54         $class = $metadata->getReflectionClass();
55         if ( ! $class) {
56             // this happens when running annotation driver in combination with
57             // static reflection services. This is not the nicest fix
58             $class = new \ReflectionClass($metadata->name);
59         }
60
61         $classAnnotations = $this->reader->getClassAnnotations($class);
62
63         if ($classAnnotations) {
64             foreach ($classAnnotations as $key => $annot) {
65                 if ( ! is_numeric($key)) {
66                     continue;
67                 }
68
69                 $classAnnotations[get_class($annot)] = $annot;
70             }
71         }
72
73         // Evaluate Entity annotation
74         if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) {
75             $entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity'];
76             if ($entityAnnot->repositoryClass !== null) {
77                 $metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
78             }
79             if ($entityAnnot->readOnly) {
80                 $metadata->markReadOnly();
81             }
82         } else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) {
83             $mappedSuperclassAnnot = $classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'];
84             $metadata->setCustomRepositoryClass($mappedSuperclassAnnot->repositoryClass);
85             $metadata->isMappedSuperclass = true;
86         } else {
87             throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
88         }
89
90         // Evaluate Table annotation
91         if (isset($classAnnotations['Doctrine\ORM\Mapping\Table'])) {
92             $tableAnnot = $classAnnotations['Doctrine\ORM\Mapping\Table'];
93             $primaryTable = array(
94                 'name' => $tableAnnot->name,
95                 'schema' => $tableAnnot->schema
96             );
97
98             if ($tableAnnot->indexes !== null) {
99                 foreach ($tableAnnot->indexes as $indexAnnot) {
100                     $index = array('columns' => $indexAnnot->columns);
101
102                     if ( ! empty($indexAnnot->name)) {
103                         $primaryTable['indexes'][$indexAnnot->name] = $index;
104                     } else {
105                         $primaryTable['indexes'][] = $index;
106                     }
107                 }
108             }
109
110             if ($tableAnnot->uniqueConstraints !== null) {
111                 foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) {
112                     $uniqueConstraint = array('columns' => $uniqueConstraintAnnot->columns);
113
114                     if ( ! empty($uniqueConstraintAnnot->name)) {
115                         $primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint;
116                     } else {
117                         $primaryTable['uniqueConstraints'][] = $uniqueConstraint;
118                     }
119                 }
120             }
121
122             if ($tableAnnot->options !== null) {
123                 $primaryTable['options'] = $tableAnnot->options;
124             }
125
126             $metadata->setPrimaryTable($primaryTable);
127         }
128
129         // Evaluate NamedNativeQueries annotation
130         if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedNativeQueries'])) {
131             $namedNativeQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedNativeQueries'];
132
133             foreach ($namedNativeQueriesAnnot->value as $namedNativeQuery) {
134                 $metadata->addNamedNativeQuery(array(
135                     'name'              => $namedNativeQuery->name,
136                     'query'             => $namedNativeQuery->query,
137                     'resultClass'       => $namedNativeQuery->resultClass,
138                     'resultSetMapping'  => $namedNativeQuery->resultSetMapping,
139                 ));
140             }
141         }
142
143         // Evaluate SqlResultSetMappings annotation
144         if (isset($classAnnotations['Doctrine\ORM\Mapping\SqlResultSetMappings'])) {
145             $sqlResultSetMappingsAnnot = $classAnnotations['Doctrine\ORM\Mapping\SqlResultSetMappings'];
146
147             foreach ($sqlResultSetMappingsAnnot->value as $resultSetMapping) {
148                 $entities = array();
149                 $columns  = array();
150                 foreach ($resultSetMapping->entities as $entityResultAnnot) {
151                     $entityResult = array(
152                         'fields'                => array(),
153                         'entityClass'           => $entityResultAnnot->entityClass,
154                         'discriminatorColumn'   => $entityResultAnnot->discriminatorColumn,
155                     );
156
157                     foreach ($entityResultAnnot->fields as $fieldResultAnnot) {
158                         $entityResult['fields'][] = array(
159                             'name'      => $fieldResultAnnot->name,
160                             'column'    => $fieldResultAnnot->column
161                         );
162                     }
163
164                     $entities[] = $entityResult;
165                 }
166
167                 foreach ($resultSetMapping->columns as $columnResultAnnot) {
168                     $columns[] = array(
169                         'name' => $columnResultAnnot->name,
170                     );
171                 }
172
173                 $metadata->addSqlResultSetMapping(array(
174                     'name'          => $resultSetMapping->name,
175                     'entities'      => $entities,
176                     'columns'       => $columns
177                 ));
178             }
179         }
180
181         // Evaluate NamedQueries annotation
182         if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedQueries'])) {
183             $namedQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries'];
184
185             if ( ! is_array($namedQueriesAnnot->value)) {
186                 throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
187             }
188
189             foreach ($namedQueriesAnnot->value as $namedQuery) {
190                 if ( ! ($namedQuery instanceof \Doctrine\ORM\Mapping\NamedQuery)) {
191                     throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
192                 }
193                 $metadata->addNamedQuery(array(
194                     'name'  => $namedQuery->name,
195                     'query' => $namedQuery->query
196                 ));
197             }
198         }
199
200         // Evaluate InheritanceType annotation
201         if (isset($classAnnotations['Doctrine\ORM\Mapping\InheritanceType'])) {
202             $inheritanceTypeAnnot = $classAnnotations['Doctrine\ORM\Mapping\InheritanceType'];
203             $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceTypeAnnot->value));
204
205             if ($metadata->inheritanceType != \Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) {
206                 // Evaluate DiscriminatorColumn annotation
207                 if (isset($classAnnotations['Doctrine\ORM\Mapping\DiscriminatorColumn'])) {
208                     $discrColumnAnnot = $classAnnotations['Doctrine\ORM\Mapping\DiscriminatorColumn'];
209                     $metadata->setDiscriminatorColumn(array(
210                         'name' => $discrColumnAnnot->name,
211                         'type' => $discrColumnAnnot->type,
212                         'length' => $discrColumnAnnot->length,
213                         'columnDefinition'    => $discrColumnAnnot->columnDefinition
214                     ));
215                 } else {
216                     $metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255));
217                 }
218
219                 // Evaluate DiscriminatorMap annotation
220                 if (isset($classAnnotations['Doctrine\ORM\Mapping\DiscriminatorMap'])) {
221                     $discrMapAnnot = $classAnnotations['Doctrine\ORM\Mapping\DiscriminatorMap'];
222                     $metadata->setDiscriminatorMap($discrMapAnnot->value);
223                 }
224             }
225         }
226
227
228         // Evaluate DoctrineChangeTrackingPolicy annotation
229         if (isset($classAnnotations['Doctrine\ORM\Mapping\ChangeTrackingPolicy'])) {
230             $changeTrackingAnnot = $classAnnotations['Doctrine\ORM\Mapping\ChangeTrackingPolicy'];
231             $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' . $changeTrackingAnnot->value));
232         }
233
234         // Evaluate annotations on properties/fields
235         /* @var $property \ReflectionProperty */
236         foreach ($class->getProperties() as $property) {
237             if ($metadata->isMappedSuperclass && ! $property->isPrivate()
238                 ||
239                 $metadata->isInheritedField($property->name)
240                 ||
241                 $metadata->isInheritedAssociation($property->name)) {
242                 continue;
243             }
244
245             $mapping = array();
246             $mapping['fieldName'] = $property->getName();
247
248             // Check for JoinColummn/JoinColumns annotations
249             $joinColumns = array();
250
251             if ($joinColumnAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumn')) {
252                 $joinColumns[] = $this->joinColumnToArray($joinColumnAnnot);
253             } else if ($joinColumnsAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) {
254                 foreach ($joinColumnsAnnot->value as $joinColumn) {
255                     $joinColumns[] = $this->joinColumnToArray($joinColumn);
256                 }
257             }
258
259             // Field can only be annotated with one of:
260             // @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany
261             if ($columnAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Column')) {
262                 if ($columnAnnot->type == null) {
263                     throw MappingException::propertyTypeIsRequired($className, $property->getName());
264                 }
265
266                 $mapping = $this->columnToArray($property->getName(), $columnAnnot);
267
268                 if ($idAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
269                     $mapping['id'] = true;
270                 }
271
272                 if ($generatedValueAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\GeneratedValue')) {
273                     $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy));
274                 }
275
276                 if ($this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Version')) {
277                     $metadata->setVersionMapping($mapping);
278                 }
279
280                 $metadata->mapField($mapping);
281
282                 // Check for SequenceGenerator/TableGenerator definition
283                 if ($seqGeneratorAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\SequenceGenerator')) {
284                     $metadata->setSequenceGeneratorDefinition(array(
285                         'sequenceName' => $seqGeneratorAnnot->sequenceName,
286                         'allocationSize' => $seqGeneratorAnnot->allocationSize,
287                         'initialValue' => $seqGeneratorAnnot->initialValue
288                     ));
289                 } else if ($this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\TableGenerator')) {
290                     throw MappingException::tableIdGeneratorNotImplemented($className);
291                 } else if ($customGeneratorAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\CustomIdGenerator')) {
292                     $metadata->setCustomGeneratorDefinition(array(
293                         'class' => $customGeneratorAnnot->class
294                     ));
295                 }
296             } else if ($oneToOneAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToOne')) {
297                 if ($idAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
298                     $mapping['id'] = true;
299                 }
300
301                 $mapping['targetEntity'] = $oneToOneAnnot->targetEntity;
302                 $mapping['joinColumns'] = $joinColumns;
303                 $mapping['mappedBy'] = $oneToOneAnnot->mappedBy;
304                 $mapping['inversedBy'] = $oneToOneAnnot->inversedBy;
305                 $mapping['cascade'] = $oneToOneAnnot->cascade;
306                 $mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval;
307                 $mapping['fetch'] = $this->getFetchMode($className, $oneToOneAnnot->fetch);
308                 $metadata->mapOneToOne($mapping);
309             } else if ($oneToManyAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToMany')) {
310                 $mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
311                 $mapping['targetEntity'] = $oneToManyAnnot->targetEntity;
312                 $mapping['cascade'] = $oneToManyAnnot->cascade;
313                 $mapping['indexBy'] = $oneToManyAnnot->indexBy;
314                 $mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval;
315                 $mapping['fetch'] = $this->getFetchMode($className, $oneToManyAnnot->fetch);
316
317                 if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
318                     $mapping['orderBy'] = $orderByAnnot->value;
319                 }
320
321                 $metadata->mapOneToMany($mapping);
322             } else if ($manyToOneAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToOne')) {
323                 if ($idAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
324                     $mapping['id'] = true;
325                 }
326
327                 $mapping['joinColumns'] = $joinColumns;
328                 $mapping['cascade'] = $manyToOneAnnot->cascade;
329                 $mapping['inversedBy'] = $manyToOneAnnot->inversedBy;
330                 $mapping['targetEntity'] = $manyToOneAnnot->targetEntity;
331                 $mapping['fetch'] = $this->getFetchMode($className, $manyToOneAnnot->fetch);
332                 $metadata->mapManyToOne($mapping);
333             } else if ($manyToManyAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToMany')) {
334                 $joinTable = array();
335
336                 if ($joinTableAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinTable')) {
337                     $joinTable = array(
338                         'name' => $joinTableAnnot->name,
339                         'schema' => $joinTableAnnot->schema
340                     );
341
342                     foreach ($joinTableAnnot->joinColumns as $joinColumn) {
343                         $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
344                     }
345
346                     foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) {
347                         $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
348                     }
349                 }
350
351                 $mapping['joinTable'] = $joinTable;
352                 $mapping['targetEntity'] = $manyToManyAnnot->targetEntity;
353                 $mapping['mappedBy'] = $manyToManyAnnot->mappedBy;
354                 $mapping['inversedBy'] = $manyToManyAnnot->inversedBy;
355                 $mapping['cascade'] = $manyToManyAnnot->cascade;
356                 $mapping['indexBy'] = $manyToManyAnnot->indexBy;
357                 $mapping['orphanRemoval'] = $manyToManyAnnot->orphanRemoval;
358                 $mapping['fetch'] = $this->getFetchMode($className, $manyToManyAnnot->fetch);
359
360                 if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
361                     $mapping['orderBy'] = $orderByAnnot->value;
362                 }
363
364                 $metadata->mapManyToMany($mapping);
365             }
366         }
367
368         // Evaluate AssociationOverrides annotation
369         if (isset($classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides'])) {
370             $associationOverridesAnnot = $classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides'];
371
372             foreach ($associationOverridesAnnot->value as $associationOverride) {
373                 $override   = array();
374                 $fieldName  = $associationOverride->name;
375
376                 // Check for JoinColummn/JoinColumns annotations
377                 if ($associationOverride->joinColumns) {
378                     $joinColumns = array();
379                     foreach ($associationOverride->joinColumns as $joinColumn) {
380                         $joinColumns[] = $this->joinColumnToArray($joinColumn);
381                     }
382                     $override['joinColumns'] = $joinColumns;
383                 }
384
385                 // Check for JoinTable annotations
386                 if ($associationOverride->joinTable) {
387                     $joinTable      = null;
388                     $joinTableAnnot = $associationOverride->joinTable;
389                     $joinTable = array(
390                         'name'      => $joinTableAnnot->name,
391                         'schema'    => $joinTableAnnot->schema
392                     );
393
394                     foreach ($joinTableAnnot->joinColumns as $joinColumn) {
395                         $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
396                     }
397
398                     foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) {
399                         $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
400                     }
401
402                     $override['joinTable'] = $joinTable;
403                 }
404
405                 $metadata->setAssociationOverride($fieldName, $override);
406             }
407         }
408
409         // Evaluate AttributeOverrides annotation
410         if (isset($classAnnotations['Doctrine\ORM\Mapping\AttributeOverrides'])) {
411             $attributeOverridesAnnot = $classAnnotations['Doctrine\ORM\Mapping\AttributeOverrides'];
412             foreach ($attributeOverridesAnnot->value as $attributeOverrideAnnot) {
413                 $attributeOverride = $this->columnToArray($attributeOverrideAnnot->name, $attributeOverrideAnnot->column);
414                 $metadata->setAttributeOverride($attributeOverrideAnnot->name, $attributeOverride);
415             }
416         }
417
418         // Evaluate @HasLifecycleCallbacks annotation
419         if (isset($classAnnotations['Doctrine\ORM\Mapping\HasLifecycleCallbacks'])) {
420             /* @var $method \ReflectionMethod */
421             foreach ($class->getMethods() as $method) {
422                 // filter for the declaring class only, callbacks from parents will already be registered.
423                 if ($method->isPublic() && $method->getDeclaringClass()->getName() == $class->name) {
424                     $annotations = $this->reader->getMethodAnnotations($method);
425
426                     if ($annotations) {
427                         foreach ($annotations as $key => $annot) {
428                             if ( ! is_numeric($key)) {
429                                 continue;
430                             }
431                             $annotations[get_class($annot)] = $annot;
432                         }
433                     }
434
435                     if (isset($annotations['Doctrine\ORM\Mapping\PrePersist'])) {
436                         $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::prePersist);
437                     }
438
439                     if (isset($annotations['Doctrine\ORM\Mapping\PostPersist'])) {
440                         $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postPersist);
441                     }
442
443                     if (isset($annotations['Doctrine\ORM\Mapping\PreUpdate'])) {
444                         $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preUpdate);
445                     }
446
447                     if (isset($annotations['Doctrine\ORM\Mapping\PostUpdate'])) {
448                         $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postUpdate);
449                     }
450
451                     if (isset($annotations['Doctrine\ORM\Mapping\PreRemove'])) {
452                         $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preRemove);
453                     }
454
455                     if (isset($annotations['Doctrine\ORM\Mapping\PostRemove'])) {
456                         $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postRemove);
457                     }
458
459                     if (isset($annotations['Doctrine\ORM\Mapping\PostLoad'])) {
460                         $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postLoad);
461                     }
462
463                     if (isset($annotations['Doctrine\ORM\Mapping\PreFlush'])) {
464                         $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preFlush);
465                     }
466                 }
467             }
468         }
469     }
470
471     /**
472      * Attempts to resolve the fetch mode.
473      *
474      * @param string $className The class name
475      * @param string $fetchMode The fetch mode
476      * @return integer The fetch mode as defined in ClassMetadata
477      * @throws MappingException If the fetch mode is not valid
478      */
479     private function getFetchMode($className, $fetchMode)
480     {
481         if( ! defined('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode)) {
482             throw MappingException::invalidFetchMode($className,  $fetchMode);
483         }
484
485         return constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode);
486     }
487
488     /**
489      * Parse the given JoinColumn as array
490      *
491      * @param   JoinColumn $joinColumn
492      * @return  array
493      */
494     private function joinColumnToArray(JoinColumn $joinColumn)
495     {
496         return array(
497             'name' => $joinColumn->name,
498             'unique' => $joinColumn->unique,
499             'nullable' => $joinColumn->nullable,
500             'onDelete' => $joinColumn->onDelete,
501             'columnDefinition' => $joinColumn->columnDefinition,
502             'referencedColumnName' => $joinColumn->referencedColumnName,
503         );
504     }
505
506     /**
507      * Parse the given Column as array
508      *
509      * @param   string $fieldName
510      * @param   Column $column
511      * @return  array
512      */
513     private function columnToArray($fieldName, Column $column)
514     {
515         $mapping = array(
516             'fieldName' => $fieldName,
517             'type'      => $column->type,
518             'scale'     => $column->scale,
519             'length'    => $column->length,
520             'unique'    => $column->unique,
521             'nullable'  => $column->nullable,
522             'precision' => $column->precision
523         );
524
525         if ($column->options) {
526             $mapping['options'] = $column->options;
527         }
528
529         if (isset($column->name)) {
530             $mapping['columnName'] = $column->name;
531         }
532
533         if (isset($column->columnDefinition)) {
534             $mapping['columnDefinition'] = $column->columnDefinition;
535         }
536
537         return $mapping;
538     }
539
540     /**
541      * Factory method for the Annotation Driver
542      *
543      * @param array|string $paths
544      * @param AnnotationReader $reader
545      * @return AnnotationDriver
546      */
547     static public function create($paths = array(), AnnotationReader $reader = null)
548     {
549         if ($reader == null) {
550             $reader = new AnnotationReader();
551         }
552
553         return new self($reader, $paths);
554     }
555 }