def __discovery_doc_descriptor(self, services, hostname=None):
    merged_api_info = self.__get_merged_api_info(services)
    descriptor = self.get_descriptor_defaults(merged_api_info,
                                              hostname=hostname)
    description = merged_api_info.description
    if not description and len(services) == 1:
      description = services[0].__doc__
    if description:
      descriptor['description'] = description
    descriptor['parameters'] = self.__standard_parameters_descriptor()
    descriptor['auth'] = self.__standard_auth_descriptor(services)
    if merged_api_info.namespace:
      descriptor['ownerDomain'] = merged_api_info.namespace.owner_domain
      descriptor['ownerName'] = merged_api_info.namespace.owner_name
      descriptor['packagePath'] = merged_api_info.namespace.package_path or ''
    else:
      if merged_api_info.owner_domain is not None:
        descriptor['ownerDomain'] = merged_api_info.owner_domain
      if merged_api_info.owner_name is not None:
        descriptor['ownerName'] = merged_api_info.owner_name
      if merged_api_info.package_path is not None:
        descriptor['packagePath'] = merged_api_info.package_path
    method_map = {}
    method_collision_tracker = {}
    rest_collision_tracker = {}
    resource_index = collections.defaultdict(list)
    resource_map = {}
    for service in services:
      remote_methods = service.all_remote_methods()
      for protorpc_meth_name, protorpc_meth_info in remote_methods.iteritems():
        method_info = getattr(protorpc_meth_info, 'method_info', None)
        if method_info is None:
          continue
        path = method_info.get_path(service.api_info)
        method_id = method_info.method_id(service.api_info)
        canonical_method_id = self._get_canonical_method_id(method_id)
        resource_path = self._get_resource_path(method_id)
        if method_id in method_collision_tracker:
          raise api_exceptions.ApiConfigurationError(
              'Method %s used multiple times, in classes %s and %s' %
              (method_id, method_collision_tracker[method_id],
               service.__name__))
        else:
          method_collision_tracker[method_id] = service.__name__
        rest_identifier = (method_info.http_method, path)
        if rest_identifier in rest_collision_tracker:
          raise api_exceptions.ApiConfigurationError(
              '%s path "%s" used multiple times, in classes %s and %s' %
              (method_info.http_method, path,
               rest_collision_tracker[rest_identifier],
               service.__name__))
        else:
          rest_collision_tracker[rest_identifier] = service.__name__
        if resource_path:
          resource_index[resource_path[0]].append((service, protorpc_meth_info))
        else:
          method_map[canonical_method_id] = self.__method_descriptor(
              service, method_info, protorpc_meth_info)
    for resource, resource_methods in resource_index.items():
      resource_map[resource] = self.__resource_descriptor(resource,
          resource_methods)
    if method_map:
      descriptor['methods'] = method_map
    if resource_map:
      descriptor['resources'] = resource_map
    schemas = self.__schemas_descriptor()
    if schemas:
      descriptor['schemas'] = schemas
    return descriptor