Compile a Pale module's resource documentation into RAML format.

    RAML calls Pale resources 'resourceTypes'. This function converts Pale
    resources into the RAML resourceType format.

    The returned string should be appended to the RAML documentation string
    before it is returned.

def generate_raml_resource_types(module):
    """Compile a Pale module's resource documentation into RAML format.

    RAML calls Pale resources 'resourceTypes'. This function converts Pale
    resources into the RAML resourceType format.

    The returned string should be appended to the RAML documentation string
    before it is returned.
    """

    from pale import extract_endpoints, extract_resources, is_pale_module
    if not is_pale_module(module):
        raise ValueError(
            """The passed in `module` (%s) is not a pale module. `paledoc`
            only works on modules with a `_module_type` set to equal
            `pale.ImplementationModule`.""")

    module_resource_types = extract_resources(module)
    raml_resource_types_unsorted = {}

    for resource in module_resource_types:
        resource_name = resource.__name__
        raml_resource_types_unsorted[resource_name] = document_resource(resource)
        if hasattr(resource, "_description"):
            modified_description = clean_description(resource._description)
            raml_resource_types_unsorted[resource_name]["description"] = modified_description

    raml_resource_types_doc = OrderedDict(sorted(raml_resource_types_unsorted.items(), key=lambda t: t[0]))

    output = StringIO()
    indent = "  "  # 2

    # blacklist of resources to ignore
    ignored_resources = []

    for resource_type in raml_resource_types_doc:

        this_resource_type = raml_resource_types_doc[resource_type]

        # add the name, ignoring the blacklist
        if resource_type not in ignored_resources:
            output.write(indent + resource_type + ":\n")

            indent += "  "  # 4

            # add the description
            if this_resource_type.get("description") != None:
                modified_description = clean_description(this_resource_type["description"])
                output.write(indent + "description: " + modified_description + "\n")

            # if there are no fields, set type directly:
            if len(this_resource_type["fields"]) == 0:
                this_type = "object"
                if this_resource_type.get("_underlying_model") != None:
                    if this_resource_type["_underlying_model"] != object:
                        if hasattr(this_resource_type._underlying_model, "_value_type") \
                        and this_resource_type["_underlying_model"]._value_type not in ignored_resources:
                            this_type = this_resource_type["_underlying_model"]._value_type
                output.write(indent + "type: " + this_type + "\n")

                indent = indent[:-2] # 2

            # if there are fields, use them as the properties, which implies type = object
            else:

                output.write(indent + "properties:\n")
                indent += "  "  # 6

                sorted_fields = OrderedDict(sorted(this_resource_type["fields"].items(), key=lambda t: t[0]))


                # add the field name, a.k.a. RAML type name
                for field in sorted_fields:
                    output.write(indent + field + ":\n")

                    # add the query parameters, a.k.a. RAML properties
                    properties = sorted_fields[field]

                    indent += "  "  # 8

                    # if this type is a list of other types, set it to type 'array' and note the item types
                    # if not, add the type from the Pale type
                    if "_underlying_model" in this_resource_type and this_resource_type["_underlying_model"] == object:
                        output.write(indent + "type: base\n")
                    elif "item_type" in properties:
                        output.write(indent + "type: array\n")
                        output.write(indent + "items: " + properties["item_type"] + "\n")
                    elif "type" in properties:
                        output.write(indent + "type: " + properties["type"].replace(" ", "_") + "\n")

                    # if extended description exists, strip newlines and whitespace and add as description
                    if properties.get("extended_description") != None:
                        modified_description = clean_description(properties["extended_description"])
                        output.write(indent + "description: " + modified_description + "\n")
                    # otherwise, use description
                    elif properties.get("description") != None:
                        modified_description = clean_description(properties["description"])
                        output.write(indent + "description: " + modified_description + "\n")

                    if properties.get("default_fields") != None:
                        output.write(indent + "properties:\n")
                        indent += "  " # 10
                        for field_name in sorted(properties["default_fields"]):
                            # @TODO check if every default field is actually a string type
                            output.write(indent + field_name + ": string\n")

                        indent = indent[:-2] # 8

                    indent = indent[:-2] # 6

                indent = indent[:-4] # 2


    raml_resource_types = output.getvalue()
    output.close()
    return raml_resource_types