private function getProperties(\ReflectionClass $reflectionClass, $properties = [], $flag = false)
    {
        $mapping = [];

        /** @var \ReflectionProperty $property */
        foreach ($this->getDocumentPropertiesReflection($reflectionClass) as $name => $property) {
            $directory = $this->guessDirName($property->getDeclaringClass());

            $type = $this->getPropertyAnnotationData($property);
            $type = $type !== null ? $type : $this->getEmbeddedAnnotationData($property);
            $type = $type !== null ? $type : $this->getHashMapAnnotationData($property);

            if ((in_array($name, $properties) && !$flag)
                || (!in_array($name, $properties) && $flag)
                || empty($type)
            ) {
                continue;
            }

            $map = $type->dump();

            // Inner object
            if ($type instanceof Embedded) {
                $map = array_replace_recursive($map, $this->getObjectMapping($type->class, $directory));
            }

            // HashMap object
            if ($type instanceof HashMap) {
                $map = array_replace_recursive($map, [
                    'type' => Nested::NAME,
                    'dynamic' => true,
                ]);
            }

            // If there is set some Raw options, it will override current ones.
            if (isset($map['options'])) {
                $options = $map['options'];
                unset($map['options']);
                $map = array_merge($map, $options);
            }

            $mapping[$type->name] = $map;
        }

        return $mapping;
    }