@param \Protobuf\Compiler\Entity            $entity
@param google\protobuf\FieldDescriptorProto $field

@return string[]
188235
protected function generateFieldWriteStatement(Entity $entity, FieldDescriptorProto $field)
    {
        $generator = new WriteFieldStatementGenerator($this->context);
        $statement = $generator->generateFieldWriteStatement($entity, $field);

        return $statement;
    }
1000371
protected function generateGetterMethod(Entity $entity, FieldDescriptorProto $field)
    {
        $fieldName  = $field->getName();
        $methodName = $this->getAccessorName('get', $field);
        $method     = MethodGenerator::fromArray([
            'name'       => $methodName,
            'body'       => 'return $this->' . $fieldName . ';',
            'docblock'   => [
                'shortDescription' => "Get '$fieldName' value",
                'tags'             => [
                    [
                        'name'        => 'return',
                        'description' => $this->getDocBlockType($field),
                    ]
                ]
            ]
        ]);

        $method->getDocblock()->setWordWrap(false);

        return $method;
    }
297329
protected function getMethodParamerters(Field $field)
    {
        $params = count($field->methodParams) == 0 ? '' : ', ' . implode(',', $field->methodParams);

        if ($field->getEloquentDataMethod() == 'enum') {
            $params = ', ' . $this->getEnumParams($field);
        }

        return $params;
    }
369056
protected function generateMethods(Entity $entity)
    {
        $result     = [];
        $descriptor = $entity->getDescriptor();
        $methods    = $descriptor->getMethodList() ?: [];

        foreach ($methods as $method) {
            $result[] = $this->generateMethod($entity, $method);
        }

        return $result;
    }
1282616
protected function _getPartsFromEntity($entity)
    {
        $parts = [];
        foreach ((array)$this->getConfig('displayField') as $displayField) {
            $value = Hash::get($entity, $displayField);

            if ($value === null && !$entity->isNew()) {
                return [];
            }

            if (!empty($value) || is_numeric($value)) {
                $parts[] = $value;
            }
        }

        return $parts;
    }
445240
public function getBlockVariables($field, $entity)
    {
        if ($field->getOption('callback')) {
            $value = call_user_func($field->getOption('callback'), $entity);
        }
        else {
            $value = $field->getData($entity);
        }

        return [
            'field_name' => $field->getName(),
            'value' => $value,
            'default_value' => $field->getOption('default_value', 'null'),
        ];
    }
152222
public function addField(\google\protobuf\FieldDescriptorProto $value)
    {
        if ($this->field === null) {
            $this->field = new \Protobuf\MessageCollection();
        }

        $this->field->add($value);
    }
900168
protected function getDoctype(FieldDescriptorProto $field)
    {
        $fieldType = $field->getType()->value();
        $phpType   = Field::getPhpType($fieldType);
        $refTypes  = [
            Type::TYPE_ENUM_VALUE    => true,
            Type::TYPE_MESSAGE_VALUE => true
        ];

        if (isset($refTypes[$fieldType])) {
            $typeName  = $field->getTypeName();
            $refEntity = $this->getEntity($typeName);

            return $refEntity->getNamespacedName();
        }

        return $phpType ?: 'mixed';
    }
355179
protected function getConditions(EntityInterface $entity)
    {
        $field = "{$this->getParentTableName()}.{$this->getForeignKey()}";
        $property = $this->getPropertyName();
        $conditions = [
            "{$field} = :{$property}" => [
                ":{$property}" => $entity->getId()
            ]
        ];
        return $conditions;
    }
1260304
protected function getFieldLabelName(FieldDescriptorProto $field)
    {
        $label = $field->getLabel()->value();
        $name  = Field::getLabelName($label);

        return $name ?: 'unknown';
    }
942668
protected function generateAddMethod(Entity $entity, FieldDescriptorProto $field)
    {
        $fieldName  = $field->getName();
        $fieldType  = $field->getType();
        $collClass  = $this->getCollectionClassName($field);
        $methodName = 'add' . $this->getClassifiedName($field);
        $typeHint   = ($fieldType !== Type::TYPE_BYTES())
            ? $this->getDoctype($field)
            : null;

        $lines[] = 'if ($this->' . $fieldName . ' === null) {';
        $lines[] = '    $this->' . $fieldName . ' = new ' . $collClass . '();';
        $lines[] = '}';
        $lines[] = null;
        $lines[] = ($fieldType !== Type::TYPE_BYTES())
            ? '$this->' . $fieldName . '->add($value);'
            : '$this->' . $fieldName . '->add(\Protobuf\Stream::wrap($value));';

        return MethodGenerator::fromArray([
            'name'       => $methodName,
            'body'       => implode(PHP_EOL, $lines),
            'parameters' => [
                [
                    'name'   => 'value',
                    'type'   => $typeHint
                ]
            ],
            'docblock'   => [
                'shortDescription' => "Add a new element to '$fieldName'",
                'tags'             => [
                    [
                        'name'        => 'param',
                        'description' => $this->getDoctype($field) . ' $value'
                    ]
                ]
            ]
        ]);
    }
440742
public function generateFieldSizeStatement(Entity $entity, FieldDescriptorProto $field)
    {
        $body     = [];
        $name     = $field->getName();
        $type     = $field->getType();
        $rule     = $field->getLabel();
        $tag      = $field->getNumber();
        $options  = $field->getOptions();
        $variable = $this->targetVar ?: '$this->' . $name;
        $isPack   = $options ? $options->getPacked() : false;

        $wire    = $isPack ? WireFormat::WIRE_LENGTH : WireFormat::getWireType($type->value(), null);
        $key     = WireFormat::getFieldKey($tag, $wire);
        $keySize = $this->getSizeCalculator()->computeVarintSize($key);

        if ($rule === Label::LABEL_REPEATED() && $isPack) {
            $itemValSttm = ($type === Type::TYPE_ENUM())
                ? '$val->value()'
                : '$val';

            $body[] = '$innerSize = 0;';
            $body[] = null;
            $body[] = 'foreach (' . $variable . ' as $val) {';
            $body[] = '    $innerSize += ' . $this->generateValueSizeStatement($type->value(), $itemValSttm) . ';';
            $body[] = '}';
            $body[] = null;
            $body[] = '$size += ' . $keySize . ';';
            $body[] = '$size += $innerSize;';
            $body[] = '$size += $calculator->computeVarintSize($innerSize);';

            return $body;
        }

        if ($type === Type::TYPE_MESSAGE() && $rule === Label::LABEL_REPEATED()) {
            $body[] = 'foreach (' . $variable . ' as $val) {';
            $body[] = '    $innerSize = $val->serializedSize($context);';
            $body[] = null;
            $body[] = '    $size += ' . $keySize . ';';
            $body[] = '    $size += $innerSize;';
            $body[] = '    $size += $calculator->computeVarintSize($innerSize);';
            $body[] = '}';

            return $body;
        }

        if ($type === Type::TYPE_ENUM() && $rule === Label::LABEL_REPEATED()) {
            $body[] = 'foreach (' . $variable . ' as $val) {';
            $body[] = '    $size += ' . $keySize . ';';
            $body[] = '    $size += ' . $this->generateValueSizeStatement($type->value(), '$val->value()') . ';';
            $body[] = '}';

            return $body;
        }

        if ($rule === Label::LABEL_REPEATED()) {
            $body[] = 'foreach (' . $variable . ' as $val) {';
            $body[] = '    $size += ' . $keySize . ';';
            $body[] = '    $size += ' . $this->generateValueSizeStatement($type->value(), '$val') . ';';
            $body[] = '}';

            return $body;
        }

        if ($type === Type::TYPE_ENUM()) {
            $body[] = '$size += ' . $keySize . ';';
            $body[] = '$size += ' . $this->generateValueSizeStatement($type->value(), $variable . '->value()') . ';';

            return $body;
        }

        if ($type !== Type::TYPE_MESSAGE()) {
            $body[] = '$size += ' . $keySize . ';';
            $body[] = '$size += ' . $this->generateValueSizeStatement($type->value(), $variable) . ';';

            return $body;
        }

        $body[] = '$innerSize = ' . $variable . '->serializedSize($context);';
        $body[] = null;
        $body[] = '$size += ' . $keySize . ';';
        $body[] = '$size += $innerSize;';
        $body[] = '$size += $calculator->computeVarintSize($innerSize);';

        return $body;
    }
1137905
public function generateBody(Entity $entity)
    {
        $lines      = [];
        $addLine    = false;
        $descriptor = $entity->getDescriptor();
        $fields     = $descriptor->getFieldList() ?: [];
        $defaults   = $this->generateDefaultValues($entity);

        foreach ($fields as $field) {
            if ($field->getLabel() !== Label::LABEL_REQUIRED()) {
                continue;
            }

            if ($field->hasDefaultValue()) {
                continue;
            }

            $item  = $this->generateRequiredFieldException($entity, $field);
            $lines = array_merge($lines, $item, [null]);
        }

        $lines[] = '$message = new self();';
        $lines[] = '$values  = array_merge([';
        $lines   = array_merge($lines, $this->addIndentation($defaults, 1));
        $lines[] = '], $values);';
        $lines[] = null;

        foreach ($fields as $field) {
            if ($field->getLabel() === Label::LABEL_REPEATED()) {
                continue;
            }

            $item  = $this->generateSetValue($entity, $field);
            $lines = array_merge($lines, $item);

            $addLine = true;
        }

        if ($addLine) {
            $lines[] = null;
        }

        foreach ($fields as $field) {
            if ($field->getLabel() !== Label::LABEL_REPEATED()) {
                continue;
            }

            $item  = $this->generateAddValue($entity, $field);
            $lines = array_merge($lines, $item, [null]);
        }

        $lines[] = 'return $message;';

        return $lines;
    }
240805
public function getAnnotations($type = 'Class', $entity, $field = null):array
    {
        $annotationReader = new AnnotationReader();

        if ($type == 'Property' && is_null($field)) {
            abort(501, 'Necessário informar o campo');
        }

        $reflection = $type == 'Class' ? new ReflectionClass($entity) : new ReflectionProperty($entity, $field);
        $annotations = $type == 'Class' ? $annotationReader->getClassAnnotations($reflection) : $annotationReader->getPropertyAnnotations($reflection);

        return $annotations;
    }
179895
private static function getEntityProValue($entity, string $proName)
    {
        $tmpNodes     = \explode('_', $proName);
        $tmpNodes     = \array_map(function ($word) {
            return \ucfirst($word);
        }, $tmpNodes);
        $proName      = \implode('', $tmpNodes);
        $getterMethod = 'get' . $proName;

        if (!\method_exists($entity, $getterMethod)) {
            throw new \InvalidArgumentException('Entity object property getter method does not exist, properName=' . $proName);
        }

        return $entity->$getterMethod();
    }
692891
public function getEntityByPk($entity, $pk, $cols = null)
    {
        // TODO: rename PK to ID
        $tbl = $this->resource->getTableName($entity);
        /* columns to select */
        $cols = ($cols) ? $cols : '*';
        $query = $this->conn->select();
        $query->from($tbl, $cols);
        foreach (array_keys($pk) as $field) {
            $query->where("$field=:$field");
        }
        $result = $this->conn->fetchRow($query, $pk);
        return $result;
    }
505758
protected function getCollectionClassName(FieldDescriptorProto $field)
    {
        $type = $field->getType();

        if ($type === Type::TYPE_MESSAGE()) {
            return '\Protobuf\MessageCollection';
        }

        if ($type === Type::TYPE_BYTES()) {
            return '\Protobuf\StreamCollection';
        }

        if ($type === Type::TYPE_ENUM()) {
            return '\Protobuf\EnumCollection';
        }

        return '\Protobuf\ScalarCollection';
    }