Map resource types to their RAML equivalents.
    Expects fields to be a list of modules - each module would be something like pale.fields.
    Expects existing_types to be a list of dict of existing types, which will take precedence
    and prevent a new type with the same name from being added.

    For more on RAML built-in-types, see:
    https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md#built-in-types

def generate_basic_type_docs(fields, existing_types):
    """Map resource types to their RAML equivalents.
    Expects fields to be a list of modules - each module would be something like pale.fields.
    Expects existing_types to be a list of dict of existing types, which will take precedence
    and prevent a new type with the same name from being added.

    For more on RAML built-in-types, see:
    https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md#built-in-types
    """

    # These types are standard in RAML 1.0
    # They should not be defined in the RAML file that we return
    # We will inherit from them in the types we define
    raml_built_in_types = {
        "any": {
            "parent": None,
        },
        "time-only": {
            "parent": "any",
        },
        "datetime": {
            "parent": "any",
            "pale_children": ["timestamp"],
        },
        "datetime-only": {
            "parent": "any",
        },
        "date-only": {
            "parent": "any",
            "pale_children": ["date"],
        },
        "number": {
            "parent": "any",
        },
        "boolean": {
            "parent": "any",
            "pale_children": ["boolean"]
        },
        "string": {
            "parent": "any",
            "pale_children": ["url", "string", "uri"],
        },
        "null": {
            "parent": "any",
        },
        "file": {
            "parent": "any",
        },
        "array": {
            "parent": "any",
            "pale_children": ["list"],
        },
        "object": {
            "parent": "any",
        },
        "union": {
            "parent": "any",
        },
        "XSD Schema": {
            "parent": "any",
        },
        "JSON Schema": {
            "parent": "any",
        },
        "integer": {
            "parent": "number",
            "pale_children": ["integer"],
        },
    }

    basic_types = {}

    # Find all classes defined in a set of resources and build up an object with
    # the relevant details of the basic types
    for field in fields:

        # if this is a Pale type, it will have a 'value_type' property,
        if hasattr(field, "value_type"):
            type_name = field.value_type.replace(" ", "_")

            # add this type only if it is not in the built-in raml types and we have
            # not added it yet
            if type_name not in raml_built_in_types \
                and type_name not in basic_types \
                and type_name not in existing_types:

                basic_types[type_name] = {}

                # strip newlines and leading whitespaces from doc string, then add as description
                if hasattr(field, "__doc__"):
                    modified_description = clean_description(field.__doc__)
                    basic_types[type_name]["description"] = modified_description

                # if this type is listed as the child of a built-in raml type,
                # use the raml type as its parent type
                for raml_type in raml_built_in_types:
                    if "pale_children" in raml_built_in_types[raml_type]:
                        if type_name in raml_built_in_types[raml_type]["pale_children"]:
                            basic_types[type_name]["type"] = raml_type
                            break

                    else:
                        # if this is not the child of a built-in raml type
                        # and if this type is a list composed of other items:
                        if hasattr(field, "is_list") and field.is_list:
                            basic_types[type_name]["type"] = "array"

                            # and the type is defined, use the defined type
                            if hasattr(field, "list_item_type") and field.list_item_type != None:
                                basic_types[type_name]["items"] = field.list_item_type
                            # otherwise, use the base type
                            else:
                                basic_types[type_name]["items"] = "base"


                        # otherwise use the pale parent class as its type
                        else:
                            pale_parent_class = field.__mro__[1]

                            # if we are at the base class, inherit from the RAML "object" type
                            if pale_parent_class.__name__ == "object":
                                basic_types[type_name]["type"] = "object"

                            # otherwise, inherit from the named parent
                            else:
                                basic_types[type_name]["type"] = pale_parent_class.value_type

    ordered_basic_types =  OrderedDict(sorted(basic_types.items(), key=lambda t: t[0]))

    basic_docs = generate_type_docs(ordered_basic_types)

    return (basic_docs, basic_types)