********************************************************************
flattens and sorts endpoint tree in service (potentially too
much nesting otherwise).

@returns {array}
function() {
    var self = this

    var endpoints = new Array()

    var flatten = function(eps, topLevel, parentPath) {
      for (var _path in eps) {
        if(self._includeUndocumented || !eps[_path].noDocument) {
          var absPath = path.join(parentPath, _path)
          endpoints.push({
            path: absPath,
            topLevel: topLevel,
            endpoint: eps[_path]
          })
          if (eps[_path].endpoints) {
            flatten(eps[_path].endpoints, false, absPath)
          }
        }
      }
    }

    flatten(self._service.endpoints, true, '/')

    var methods = _o('../Endpoint').prototype.ALL_METHODS

    for (var i = 0; i < endpoints.length; i++) {
      var operations = methods.map(function(m) {
          if (endpoints[i].endpoint[m] &&
            (self._includeUndocumented || !endpoints[i].endpoint[m].noDocument) &&
            (m != "options" || self._service.generateOptionsMethodsInDocs)) {
            return self._generateOperationDescriptor(m, endpoints[i].endpoint[m], endpoints[i].path)
          }
          return undefined
        }).filter(function(e) {
          return e ? true : false;
        })

      if (operations.length == 0) {
        continue
      }
      endpoints[i] = {
        path: endpoints[i].path,
        description: endpoints[i].endpoint.description,
        topLevel: endpoints[i].topLevel,
        parameters: self._generateParameterDescriptors(endpoints[i].endpoint.parameters, undefined, endpoints[i].path),
        allowUnauthenticated: endpoints[i].endpoint.allowUnauthenticated,
        operations: operations
      }
    }

    endpoints = _.sortBy(endpoints, ['path'])

    return endpoints
  }