Deserialize the annotation's property.

@param Annotations\AbstractAnnotation $annotation
@param string                         $property
@param mixed                          $value

@return mixed
356232
private function doDeserializeProperty(Annotations\AbstractAnnotation $annotation, $property, $value)
    {
        // property is primitive type
        if (array_key_exists($property, $annotation::$_types)) {
            return $this->doDeserializeBaseProperty($annotation::$_types[$property], $value);
        }
        // property is embedded annotation
        foreach ($annotation::$_nested as $class => $declaration) {
            // property is an annotation
            if (is_string($declaration) && $declaration === $property) {
                return $this->doDeserialize($value, $class);
            }

            // property is an annotation array
            if (is_array($declaration) && count($declaration) === 1 && $declaration[0] === $property) {
                $annotationArr = [];
                foreach ($value as $v) {
                    $annotationArr[] = $this->doDeserialize($v, $class);
                }
                return $annotationArr;
            }

            // property is an annotation hash map
            if (is_array($declaration) && count($declaration) === 2 && $declaration[0] === $property) {
                $key = $declaration[1];
                $annotationHash = [];
                foreach ($value as $k => $v) {
                    $annotation = $this->doDeserialize($v, $class);
                    $annotation->$key = $k;
                    $annotationHash[$k] = $annotation;
                }
                return $annotationHash;
            }
        }

        return $value;
    }
51440
private function embedOneToProperty($embed, AbstractField $annotation)
    {
        $className = $annotation->target;

        try {
            $reflectClass = new \ReflectionClass($className);
        } catch (\Exception $exception) {
            return $embed;
        }

        $property = new \stdClass();

        foreach ($reflectClass->getProperties() as $field) {
            if ($field->isStatic()) {
                continue;
            }

            $annotation = $this->annotationParser->getPropertyAnnotation($field);

            $propertyName = $annotation->name ?? $field->getName();

            try {
                $reflectProperty = new \ReflectionProperty($embed, $propertyName);

                $reflectProperty->setAccessible(true);
                $fieldValue = $reflectProperty->getValue($embed);

                $propertyValue = $this->fieldToProperty($fieldValue, $annotation);


            } catch (\Exception $exception) {
                $propertyValue = null;
            }

            $property->{$propertyName} = $propertyValue;
        }

        return $property;
    }
375867
public static function getPropertiesAnnotations($className, $annotationClassName = null)
    {
        if(null === $annotationClassName)
        {
            return static::$annotations[$className]['Properties'] ?? [];
        }
        $result = [];
        foreach(static::$annotations[$className]['Properties'] ?? [] as $propertyName => $annotations)
        {
            foreach($annotations as $annotation)
            {
                if($annotation instanceof $annotationClassName)
                {
                    $result[$propertyName][] = $annotation;
                }
            }
        }
        return $result;
    }
562828
public static function getPropertyAnnotations($className, $propertyName, $annotationClassName = null)
    {
        if(!isset(static::$annotations[$className]['Properties'][$propertyName]))
        {
            return [];
        }
        if(null === $annotationClassName)
        {
            return static::$annotations[$className]['Properties'][$propertyName];
        }
        else
        {
            $result = [];
            foreach(static::$annotations[$className]['Properties'][$propertyName] as $annotation)
            {
                if($annotation instanceof $annotationClassName)
                {
                    $result[] = $annotation;
                }
            }
            return $result;
        }
    }
875682
public static function parseByManyToMany($model, $propertyName, $annotation)
    {
        $className = BeanFactory::getObjectClass($model);

        $struct = new ManyToMany($className, $propertyName, $annotation);
        $middleModel = $struct->getMiddleModel();
        $middleLeftField = $struct->getMiddleLeftField();
        $leftField = $struct->getLeftField();

        foreach($model->$propertyName as $index => $row)
        {
            if(!$row instanceof $middleModel)
            {
                $row = $middleModel::newInstance($row);
                $model->$propertyName[$index] = $row;
            }
            $row[$middleLeftField] = $model->$leftField;
            $row->insert();
        }
    }
650405
public function parse($value, $annotation = null)
    {
        if (false === ($value = filter_var($value, FILTER_VALIDATE_INT))) {
            throw new ParserException("Raw value must be integer. Invalid value '{$value}' given.");
        }

        return $value;
    }
1368982
public static function readClass( $class , $annotation = null ) {

		$ref = $class instanceof ReflectionClass ? $class : new ReflectionClass( $class );

		return $annotation ? static::reader()->getClassAnnotation( $ref , $annotation ) : static::reader()->getClassAnnotations( $ref );

	}
969224
protected function buildPropertyAnnotation($property, &$structure) {
        $field = array(
            'name' => $this->convertNaming($property->getName()),
            'type' => 'string',
        );
        $association = array();
        $validators = array();
        $skipValidator = false;
        $saveField = false;
        $fieldIsId = false;
        $annotations = $this->annoReader->getPropertyAnnotations($property);
        foreach ($annotations as $annotation) {
            $className = get_class($annotation);
            /** Get Constraints from Symfony Validator */
            if (strpos(get_class($annotation), 'Symfony\Component\Validator\Constraints') === 0) {
                $validators[] = array_merge(
                    array('field'=>$this->convertNaming($property->getName())),
                    $this->getValidator(substr($className, 40),$annotation)
                );
            }
            switch(get_class($annotation)) {
                case 'Tpg\ExtjsBundle\Annotation\Model\Field':
                    $field['type'] = $annotation->type;
                    break;
                case 'Doctrine\ORM\Mapping\Id':
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\Id':
                    $field['useNull'] = true;
                    $field['persist'] = false;
                    $skipValidator = true;
                    $fieldIsId = true;
                    break;
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\Timestamp':
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\Date':
                    $field['type'] = "date";
                    break;
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\Float':
                    $field['type'] = "float";
                    break;
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\Boolean':
                    $field['type'] = "boolean";
                    break;
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\Hash':
                    $field['type'] = "auto";
                    break;
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\Int':
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\Increment':
                    $field['type'] = "int";
                    break;
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\String':
                    $field['type'] = "string";
                    break;
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\Field':
                    $field['type'] = $this->getColumnType($annotation->type);
                    break;
                case 'Doctrine\ORM\Mapping\Column':
                    $field['type'] = $this->getColumnType($annotation->type);
                    if ($field['type'] === "date") {
                        $field['dateFormat'] = \DateTime::ISO8601;
                    }
                    $validators[] = array('type'=>'presence', 'field'=>$this->convertNaming($property->getName()));
                    break;
                case 'JMS\Serializer\Annotation\SerializedName':
                    $field['name'] = $annotation->name;
                    break;
                case 'JMS\Serializer\Annotation\Type':
                    if (stripos($annotation->name, "DateTime") === 0) {
                        $type = $annotation->name;
                        if ($type === "DateTime") {
                            $field['dateFormat'] = \DateTime::ISO8601;
                        } else {
                            $format = explode(',',
                                substr(
                                    $type,
                                    stripos($type, '<')+2,
                                    -2
                                )
                            );
                            $field['dateFormat'] = $format[0];
                        }
                    }
                    break;
                case 'Doctrine\ORM\Mapping\OneToOne':
                    $association['type'] = substr(get_class($annotation), 21);
                    $association['name'] = $property->getName();
                    $association['model'] = $this->getModelName($annotation->targetEntity);
                    $association['entity'] = $annotation->targetEntity;
                    if (!isset($association['key']) || empty($association['key']))
                        $association['key'] = $this->tryToGetJoinColumnNameOfMappedBy($annotation);
                    break;
                case 'Doctrine\ORM\Mapping\OneToMany':
                    $association['type'] = substr(get_class($annotation), 21);
                    $association['name'] = $property->getName();
                    $association['model'] = $this->getModelName($annotation->targetEntity);
                    $association['entity'] = $annotation->targetEntity;
                    $association['key'] = $this->tryToGetJoinColumnNameOfMappedBy($annotation);
                    break;
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\EmbedMany':
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\EmbedOne':
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\ReferenceMany':
                case 'Doctrine\ODM\MongoDB\Mapping\Annotations\ReferenceOne':
                    if ($annotation->targetDocument) {
                        $association['type'] = substr(get_class($annotation), 41);
                        $association['name'] = $property->getName();
                        $association['model'] = $this->getModelName($annotation->targetDocument);
                        $association['entity'] = $annotation->targetDocument;
                    } else {
                        $field['type'] = "auto";
                    }
                    break;
                case 'Doctrine\ORM\Mapping\ManyToOne':
                    $association['type'] = substr(get_class($annotation), 21);
                    $association['name'] = $property->getName();
                    $association['model'] = $this->getModelName($annotation->targetEntity);
                    $association['entity'] = $annotation->targetEntity;
                    break;
                case 'Doctrine\ORM\Mapping\ManyToMany':
                    $association['type'] = 'ManyToMany';
                    $association['name'] = $property->getName();
                    $association['model'] = $this->getModelName($annotation->targetEntity);
                    $association['entity'] = $annotation->targetEntity;
                    break;
                case 'Doctrine\ORM\Mapping\JoinColumns':
                    if (count($annotation->value) > 1) {
                      throw new \Exception('Multiple foreign key is not supported');
                    }
                    $saveField = true;
                    $field['name'] = $this->convertNaming($annotation->value[0]->name);
                    $field['type'] = $this->getEntityColumnType($association['entity'], $annotation->value[0]->referencedColumnName);
                    $field['useNull'] = true;
                    $association['key'] = $this->convertNaming($annotation->value[0]->name);
                    break;
                case 'Doctrine\ORM\Mapping\JoinColumn':
                    $saveField = true;
                    $field['name'] = $this->convertNaming($annotation->name);
                    $field['type'] = $this->getEntityColumnType($association['entity'], $annotation->referencedColumnName);
                    $field['useNull'] = true;
                    $association['key'] = $this->convertNaming($annotation->name);
                    $field['mapping'] = $property->getName() . '.' . $annotation->referencedColumnName;
                    break;
            }
        }
        if($fieldIsId){
            $structure['idProperty'] = $field['name'];
        }

        /** Add the ability to override field parameter */
        if (isset($this->fieldsParams[$field['type']])) {
          $field = array_merge($field, $this->fieldsParams[$field['type']]);
        }

        if (!empty($association)) {
            if ($association['model'] === null) {
                /** Related model is not available, skip this field. */
                return array();
            }
            $structure['associations'][] = $association;
        }
        if ($saveField || empty($association)) {
            $structure['fields'][$field['name']] = $field;
        }
        if (!empty($validators) && !$skipValidator) {
            $structure['validators'] = array_merge($structure['validators'], $validators);
        }
        return $field;
    }
836048
public function processAnnotation($annotation, PropertyInformation $info): void
    {
        // Standalone Enumerator annotation.
        if ($annotation instanceof Enumerator) {
            $info->addEnumeratorToGenerate($annotation);
            $annotation->property = $info->getName();
            if (! $info->getType() && $annotation->getType()) {
                $info->setType($annotation->getType());
            }
            return;
        }

        // Only process Generate annotations from this point.
        if (!$annotation instanceof Generate) {
            return;
        }

        $info->setIsGenerator(true);

        if ($annotation->getEnumerators()) {
            $annotation->setDefaultVisibility(Generate::VISIBILITY_NONE);
            foreach ($annotation->getEnumerators() as $enumerator) {
                $info->addEnumeratorToGenerate($enumerator);
            }
        } else {
            $annotation->setDefaultVisibility(Generate::VISIBILITY_PUBLIC);
        }

        // By default no method is generated.
        //
        // Each processor can enforce a limitation on the generated methods.
        // If processor A lets a method be private, and processor B tells it to
        // be protected, it will end up private.

        $info->limitMaximumGetVisibility(
            Generate::getMostLimitedVisibility($annotation->getGet(), $annotation->getIs())
        );
        $info->limitMaximumSetVisibility(
            Generate::getMostLimitedVisibility($annotation->getSet())
        );
        $info->limitMaximumAddVisibility(
            Generate::getMostLimitedVisibility($annotation->getAdd(), $annotation->getSet())
        );
        $info->limitMaximumRemoveVisibility(
            Generate::getMostLimitedVisibility($annotation->getRemove(), $annotation->getSet())
        );

        null === $info->getType() && $annotation->getType() && $info->setType($annotation->getType());
        null !== $annotation->getType() && $info->setTypeHint($annotation->getType());
        null !== $annotation->getEncryptionAlias() && $info->setEncryptionAlias($annotation->getEncryptionAlias());

        // Enforce always
        $info->setGenerateStrict($annotation->isStrict());
        $info->setIsGenerator(true);
    }
540961
public function parse($value, $annotation = null)
    {
        if ('' === $value) return true; // implicit boolean

        $json = JsonType::jsonDecode($value);

        if (JSON_ERROR_NONE === json_last_error()) {
            return $json;
        }
        elseif (false !== ($int = filter_var($value, FILTER_VALIDATE_INT))) {
            return $int;
        }
        elseif (false !== ($float = filter_var($value, FILTER_VALIDATE_FLOAT))) {
            return $float;
        }

        return $value;
    }
214003
public function getPropertyAnnotation(\ReflectionProperty $property)
    {
        $annot = $this->reader->getPropertyAnnotation($property, '\Represent\Annotations\Property');

        if (!$annot) {
            return false;
        }

        return $annot;
    }
44613
protected static function createProperty(\ReflectionProperty $reflectionProperty)
    {
        $property = new Property();
        $property->setName($reflectionProperty->getName());
        
        $annotationReader = new AnnotationReader();
        $annotations = $annotationReader->getPropertyAnnotations($reflectionProperty);
        foreach ($annotations as $annotation) {
            $annotationClassName = get_class($annotation);
            if ($annotationClassName == 'Doctrine\ORM\Mapping\Column' || $annotationClassName == 'Doctrine\ORM\Mapping\Id') {
                $property->setAnnotation($annotation);
                $property->setType(Property::PROPERTY_TYPE_COLUMN);
            } elseif ($annotationClassName == 'Doctrine\ORM\Mapping\ManyToOne' || $annotationClassName == 'Doctrine\ORM\Mapping\OneToOne') {
                $property->setAnnotation($annotation);
                $property->setType(Property::PROPERTY_TYPE_REF_ONE);
                $property->setTargetEntity($annotation->targetEntity);
            } elseif ($annotationClassName == 'Doctrine\ORM\Mapping\ManyToMany' || $annotationClassName == 'Doctrine\ORM\Mapping\OneToMany') {
                $property->setAnnotation($annotation);
                $property->setType(Property::PROPERTY_TYPE_REF_MANY);
                $property->setTargetEntity($annotation->targetEntity);
            }
        }
        
        if ($property->getType() == -1) {
            throw new \Exception(
                'Entity "' . $reflectionProperty->getDeclaringClass()->getName()
                . '": defining annotation is missing at property "' . $property->getName() . '"!'
            );
        }
        
        return $property;
    }
671424
protected function getValueByAnnotatedType(ReflectionProperty $property, $value)
    {
        $comment = $property->getDocComment();
        if (preg_match('/@var (.+?)(\|null)? /', $comment, $matches)) {
            switch ($matches[1]) {
                case 'integer':
                case 'int':
                    $value = (int) $value;
                    break;
                case 'float':
                    $value = (float) $value;
                    break;
            }
        }

        return $value;
    }
961221
public static function initByManyToMany($model, $propertyName, $annotation)
    {
        $className = BeanFactory::getObjectClass($model);

        if(class_exists($annotation->model))
        {
            $modelClass = $annotation->model;
        }
        else
        {
            $modelClass = Imi::getClassNamespace($className) . '\\' . $annotation->model;
        }

        $struct = new ManyToMany($className, $propertyName, $annotation);
        $leftField = $struct->getLeftField();
        $rightField = $struct->getRightField();
        $middleTable = ModelManager::getTable($struct->getMiddleModel());
        $rightTable = ModelManager::getTable($struct->getRightModel());

        static::parseManyToManyQueryFields($struct->getMiddleModel(), $struct->getRightModel(), $middleFields, $rightFields);
        $fields = static::mergeManyToManyFields($middleTable, $middleFields, $rightTable, $rightFields);
        
        $model->$propertyName = new ArrayList($struct->getMiddleModel());
        $model->{$annotation->rightMany} = new ArrayList($struct->getRightModel());
        
        if(null !== $model->$leftField)
        {
            $list = Db::query(ModelManager::getDbPoolName($className))
                        ->table($rightTable)
                        ->field(...$fields)
                        ->join($middleTable, $middleTable . '.' . $struct->getMiddleRightField(), '=', $rightTable . '.' . $rightField)
                        ->where($middleTable . '.' . $struct->getMiddleLeftField(), '=', $model->$leftField)
                        ->select()
                        ->getArray();
            if(null !== $list)
            {
                // 关联数据
                static::appendMany($model->$propertyName, $list, $middleFields, $struct->getMiddleModel());

                // 右侧表数据
                static::appendMany($model->{$annotation->rightMany}, $list, $rightFields, $struct->getRightModel());

            }
        }
    }
315291
private function fieldToProperty($fieldValue, AbstractField $annotation)
    {
        $fieldType = $annotation->type;

        switch ($fieldType) {
            case 'string':
                $propertyValue = strval($fieldValue);
                break;
            case 'bool':
                $propertyValue = boolval($fieldValue);
                break;
            case 'int':
                $propertyValue = intval($fieldValue);
                break;
            case 'float':
                $propertyValue = floatval($fieldValue);
                break;
            case 'array':
                $propertyValue = is_array($fieldValue) ? $fieldValue : (array)($fieldValue);
                break;
            case 'date':
                /** @var \DateTime $fieldValue */
                $propertyValue = ($fieldValue instanceof \DateTime) ? new UTCDateTime($fieldValue) : $fieldValue;
                break;
            case 'id':
                $propertyValue = $fieldValue instanceof ObjectId ? $fieldValue : new ObjectId();
                break;
            case 'embedOne':
                $propertyValue = $this->embedOneToProperty($fieldValue, $annotation);
                break;
            case 'embedMany':
                $propertyValue = $this->embedManyToProperty((array)$fieldValue, $annotation);
                break;
            case 'raw':
            default:
                $propertyValue = $fieldValue;
                break;
        }

        return $propertyValue;
    }
1192589
public function parse($value, $annotation = null)
    {
        if (false === ($value = filter_var($value, FILTER_VALIDATE_FLOAT))) {
            throw new ParserException("Raw value must be float. Invalid value '{$value}' given.");
        }

        return $value;
    }
1082813
@Nullable
  private static <A extends Annotation> A getAnnotation(PropertyDescriptor descriptor,
      Class<A> type) {
    A a = null;
    if (descriptor.getWriteMethod() != null) {
      a = descriptor.getWriteMethod().getAnnotation(type);
    }
    if (a == null && descriptor.getReadMethod() != null) {
      a = descriptor.getReadMethod().getAnnotation(type);
    }
    return a;
  }