private function parseProperties($class)
    {
        $ret = [];

        $defaults = $class->getDefaultProperties();

        foreach ($class->getProperties() as $property) {
            $tags = self::parseDocCommentTags($property->getDocComment());
            list($type, $description) = $this->tokenize($tags[self::T_VAR], 2);

            $p = [];
            if (strpos($type, '[]') > 0) {
                $type = str_replace('[]', '', $type);
                $p['type'] = 'array';
                $p['xml'] = ['name' => preg_replace('!s$!', '', $property->name), 'wrapped' => true];
                if ($this->isDefinedType($type)) {
                    $p['items'] = ['$ref' => $this->getDefinition($type)];
                } else {
                    $p['items'] = ['type' => $type];
                }
            } elseif ($this->isDefinedType($type)) {
                $p['$ref'] = $this->getDefinition($type);
            } else {
                $p['type'] = $type;
                $enums = isset($tags[self::T_ENUM]) ? $this->mixedToArray($tags[self::T_ENUM]) : [];
                foreach ($enums as $enum) {
                    $p['enum'] = $this->tokenize($enum);
                }
            }

            if (isset($tags[self::T_FORMAT])) {
                $p['format'] = $tags[self::T_FORMAT];
            }

            if (isset($tags[self::T_EXAMPLE])) {
                $p['example'] = $tags[self::T_EXAMPLE];
            }

            if (isset($tags[self::T_REQUIRED])) {
                $p['required'] = true;
            }

            if (!empty($description)) {
                $p['description'] = $description;
            }

            if (!is_null($defaults[$property->name])) {
                $p['default'] = $defaults[$property->name];
            }

            $ret[$property->name] = $p;
        }
        return $ret;
    }