# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import collections
import itertools
import logging
import time

from google.protobuf import timestamp_pb2

from api import resource_name_converters as rnc
from api.v3.api_proto import feature_objects_pb2
from api.v3.api_proto import issues_pb2
from api.v3.api_proto import issue_objects_pb2
from api.v3.api_proto import project_objects_pb2
from api.v3.api_proto import user_objects_pb2

from framework import exceptions
from framework import filecontent
from framework import framework_bizobj
from framework import framework_constants
from framework import framework_helpers
from proto import tracker_pb2
from project import project_helpers
from tracker import attachment_helpers
from tracker import field_helpers
from tracker import tracker_bizobj as tbo
from tracker import tracker_helpers

Choice = project_objects_pb2.FieldDef.EnumTypeSettings.Choice

# Ingest/convert dicts for ApprovalStatus.
_V3_APPROVAL_STATUS = issue_objects_pb2.ApprovalValue.ApprovalStatus.Value
_APPROVAL_STATUS_INGEST = {
  _V3_APPROVAL_STATUS('APPROVAL_STATUS_UNSPECIFIED'): None,
  _V3_APPROVAL_STATUS('NOT_SET'): tracker_pb2.ApprovalStatus.NOT_SET,
  _V3_APPROVAL_STATUS('NEEDS_REVIEW'): tracker_pb2.ApprovalStatus.NEEDS_REVIEW,
  _V3_APPROVAL_STATUS('NA'): tracker_pb2.ApprovalStatus.NA,
  _V3_APPROVAL_STATUS('REVIEW_REQUESTED'):
      tracker_pb2.ApprovalStatus.REVIEW_REQUESTED,
  _V3_APPROVAL_STATUS('REVIEW_STARTED'):
      tracker_pb2.ApprovalStatus.REVIEW_STARTED,
  _V3_APPROVAL_STATUS('NEED_INFO'): tracker_pb2.ApprovalStatus.NEED_INFO,
  _V3_APPROVAL_STATUS('APPROVED'): tracker_pb2.ApprovalStatus.APPROVED,
  _V3_APPROVAL_STATUS('NOT_APPROVED'): tracker_pb2.ApprovalStatus.NOT_APPROVED,
}
_APPROVAL_STATUS_CONVERT = {
  val: key for key, val in _APPROVAL_STATUS_INGEST.items()}


class Converter(object):
  """Class to manage converting objects between the API and backend layer."""

  def __init__(self, mc, services):
    # type: (MonorailContext, Services) -> Converter
    """Create a Converter with the given MonorailContext and Services.

    Args:
      mc: MonorailContext object containing the MonorailConnection to the DB
            and the requester's AuthData object.
      services: Services object for connections to backend services.
    """
    self.cnxn = mc.cnxn
    self.user_auth = mc.auth
    self.services = services

  # Hotlists

  def ConvertHotlist(self, hotlist):
    # type: (proto.feature_objects_pb2.Hotlist)
    #    -> api_proto.feature_objects_pb2.Hotlist
    """Convert a protorpc Hotlist into a protoc Hotlist."""

    hotlist_resource_name = rnc.ConvertHotlistName(hotlist.hotlist_id)
    members_by_id = rnc.ConvertUserNames(
        hotlist.owner_ids + hotlist.editor_ids)
    default_columns = self._ComputeIssuesListColumns(hotlist.default_col_spec)
    if hotlist.is_private:
      hotlist_privacy = feature_objects_pb2.Hotlist.HotlistPrivacy.Value(
          'PRIVATE')
    else:
      hotlist_privacy = feature_objects_pb2.Hotlist.HotlistPrivacy.Value(
          'PUBLIC')

    return feature_objects_pb2.Hotlist(
        name=hotlist_resource_name,
        display_name=hotlist.name,
        owner=members_by_id.get(hotlist.owner_ids[0]),
        editors=[
            members_by_id.get(editor_id) for editor_id in hotlist.editor_ids
        ],
        summary=hotlist.summary,
        description=hotlist.description,
        default_columns=default_columns,
        hotlist_privacy=hotlist_privacy)

  def ConvertHotlists(self, hotlists):
    # type: (Sequence[proto.feature_objects_pb2.Hotlist])
    #    -> Sequence[api_proto.feature_objects_pb2.Hotlist]
    """Convert protorpc Hotlists into protoc Hotlists."""
    return [self.ConvertHotlist(hotlist) for hotlist in hotlists]

  def ConvertHotlistItems(self, hotlist_id, items):
    # type: (int, Sequence[proto.features_pb2.HotlistItem]) ->
    #     Sequence[api_proto.feature_objects_pb2.Hotlist]
    """Convert a Sequence of protorpc HotlistItems into a Sequence of protoc
       HotlistItems.

    Args:
      hotlist_id: ID of the Hotlist the items belong to.
      items: Sequence of HotlistItem protorpc objects.

    Returns:
      Sequence of protoc HotlistItems in the same order they are given in
        `items`.
      In the rare event that any issues in `items` are not found, they will be
        omitted from the result.
    """
    issue_ids = [item.issue_id for item in items]
    # Converting HotlistItemNames and IssueNames both require looking up the
    # issues in the hotlist. However, we want to keep the code clean and
    # readable so we keep the two processes separate.
    resource_names_dict = rnc.ConvertHotlistItemNames(
        self.cnxn, hotlist_id, issue_ids, self.services)
    issue_names_dict = rnc.ConvertIssueNames(
        self.cnxn, issue_ids, self.services)
    adders_by_id = rnc.ConvertUserNames([item.adder_id for item in items])

    # Filter out items whose issues were not found.
    found_items = [
        item for item in items if resource_names_dict.get(item.issue_id) and
        issue_names_dict.get(item.issue_id)
    ]
    if len(items) != len(found_items):
      found_ids = [item.issue_id for item in found_items]
      missing_ids = [iid for iid in issue_ids if iid not in found_ids]
      logging.info('HotlistItem issues %r not found' % missing_ids)

    # Generate user friendly ranks (0, 1, 2, 3,...) that are exposed to API
    # clients, instead of using padded ranks (1, 11, 21, 31,...).
    sorted_ranks = sorted(item.rank for item in found_items)
    friendly_ranks_dict = {
        rank: friendly_rank for friendly_rank, rank in enumerate(sorted_ranks)
    }

    api_items = []
    for item in found_items:
      api_item = feature_objects_pb2.HotlistItem(
          name=resource_names_dict.get(item.issue_id),
          issue=issue_names_dict.get(item.issue_id),
          rank=friendly_ranks_dict[item.rank],
          adder=adders_by_id.get(item.adder_id),
          note=item.note)
      if item.date_added:
        api_item.create_time.FromSeconds(item.date_added)
      api_items.append(api_item)

    return api_items

  # Issues

  def _ConvertComponentValues(self, issue):
    # proto.tracker_pb2.Issue ->
    #     Sequence[api_proto.issue_objects_pb2.Issue.ComponentValue]
    """Convert the status string on issue into a ComponentValue."""
    component_values = []
    component_ids = itertools.chain(
        issue.component_ids, issue.derived_component_ids)
    ids_to_names = rnc.ConvertComponentDefNames(
        self.cnxn, component_ids, issue.project_id, self.services)

    for component_id in issue.component_ids:
      if component_id in ids_to_names:
        component_values.append(
            issue_objects_pb2.Issue.ComponentValue(
                component=ids_to_names[component_id],
                derivation=issue_objects_pb2.Derivation.Value(
                    'EXPLICIT')))
    for derived_component_id in issue.derived_component_ids:
      if derived_component_id in ids_to_names:
        component_values.append(
            issue_objects_pb2.Issue.ComponentValue(
                component=ids_to_names[derived_component_id],
                derivation=issue_objects_pb2.Derivation.Value('RULE')))

    return component_values

  def _ConvertStatusValue(self, issue):
    # proto.tracker_pb2.Issue -> api_proto.issue_objects_pb2.Issue.StatusValue
    """Convert the status string on issue into a StatusValue."""
    derivation = issue_objects_pb2.Derivation.Value(
        'DERIVATION_UNSPECIFIED')
    if issue.status:
      derivation = issue_objects_pb2.Derivation.Value('EXPLICIT')
    else:
      derivation = issue_objects_pb2.Derivation.Value('RULE')
    return issue_objects_pb2.Issue.StatusValue(
        status=issue.status or issue.derived_status, derivation=derivation)

  def _ConvertAmendments(self, amendments, user_display_names):
    # type: (Sequence[proto.tracker_pb2.Amendment], Mapping[int, str]) ->
    #     Sequence[api_proto.issue_objects_pb2.Comment.Amendment]
    """Convert protorpc Amendments to protoc Amendments.

    Args:
      amendments: the amendments to convert
      user_display_names: map from user_id to display name for all users
          involved in the amendments.

    Returns:
      The converted amendments.
    """
    results = []
    for amendment in amendments:
      field_name = tbo.GetAmendmentFieldName(amendment)
      new_value = tbo.AmendmentString_New(amendment, user_display_names)
      results.append(
          issue_objects_pb2.Comment.Amendment(
              field_name=field_name,
              new_or_delta_value=new_value,
              old_value=amendment.oldvalue))
    return results

  def _ConvertAttachments(self, attachments, project_name):
    # type: (Sequence[proto.tracker_pb2.Attachment], str) ->
    #     Sequence[api_proto.issue_objects_pb2.Comment.Attachment]
    """Convert protorpc Attachments to protoc Attachments."""
    results = []
    for attach in attachments:
      if attach.deleted:
        state = issue_objects_pb2.IssueContentState.Value('DELETED')
        size, thumbnail_uri, view_uri, download_uri = None, None, None, None
      else:
        state = issue_objects_pb2.IssueContentState.Value('ACTIVE')
        size = attach.filesize
        download_uri = attachment_helpers.GetDownloadURL(attach.attachment_id)
        view_uri = attachment_helpers.GetViewURL(
            attach, download_uri, project_name)
        thumbnail_uri = attachment_helpers.GetThumbnailURL(attach, download_uri)
      results.append(
          issue_objects_pb2.Comment.Attachment(
              filename=attach.filename,
              state=state,
              size=size,
              media_type=attach.mimetype,
              thumbnail_uri=thumbnail_uri,
              view_uri=view_uri,
              download_uri=download_uri))
    return results

  def ConvertComments(self, issue_id, comments):
    # type: (int, Sequence[proto.tracker_pb2.IssueComment])
    #     -> Sequence[api_proto.issue_objects_pb2.Comment]
    """Convert protorpc IssueComments from issue into protoc Comments."""
    issue = self.services.issue.GetIssue(self.cnxn, issue_id)
    users_by_id = self.services.user.GetUsersByIDs(
        self.cnxn, tbo.UsersInvolvedInCommentList(comments))
    (user_display_names,
     _user_display_emails) = framework_bizobj.CreateUserDisplayNamesAndEmails(
         self.cnxn, self.services, self.user_auth, users_by_id.values())
    comment_names_dict = rnc.CreateCommentNames(
        issue.local_id, issue.project_name,
        [comment.sequence for comment in comments])
    approval_ids = [
        comment.approval_id
        for comment in comments
        if comment.approval_id is not None  # In case of a 0 approval_id.
    ]
    approval_ids_to_names = rnc.ConvertApprovalDefNames(
        self.cnxn, approval_ids, issue.project_id, self.services)

    converted_comments = []
    for comment in comments:
      if comment.is_spam:
        state = issue_objects_pb2.IssueContentState.Value('SPAM')
      elif comment.deleted_by:
        state = issue_objects_pb2.IssueContentState.Value('DELETED')
      else:
        state = issue_objects_pb2.IssueContentState.Value('ACTIVE')
      comment_type = issue_objects_pb2.Comment.Type.Value('COMMENT')
      if comment.is_description:
        comment_type = issue_objects_pb2.Comment.Type.Value('DESCRIPTION')
      converted_attachments = self._ConvertAttachments(
          comment.attachments, issue.project_name)
      converted_amendments = self._ConvertAmendments(
          comment.amendments, user_display_names)
      converted_comment = issue_objects_pb2.Comment(
          name=comment_names_dict[comment.sequence],
          state=state,
          type=comment_type,
          create_time=timestamp_pb2.Timestamp(seconds=comment.timestamp),
          attachments=converted_attachments,
          amendments=converted_amendments)
      if comment.content:
        converted_comment.content = comment.content
      if comment.user_id:
        converted_comment.commenter = rnc.ConvertUserName(comment.user_id)
      if comment.inbound_message:
        converted_comment.inbound_message = comment.inbound_message
      if comment.approval_id and comment.approval_id in approval_ids_to_names:
        converted_comment.approval = approval_ids_to_names[comment.approval_id]
      converted_comments.append(converted_comment)
    return converted_comments

  def ConvertIssue(self, issue):
    # type: (proto.tracker_pb2.Issue) -> api_proto.issue_objects_pb2.Issue
    """Convert a protorpc Issue into a protoc Issue."""
    issues = self.ConvertIssues([issue])
    if len(issues) < 1:
      raise exceptions.NoSuchIssueException()
    if len(issues) > 1:
      logging.warning('More than one converted issue returned: %s', issues)
    return issues[0]

  def ConvertIssues(self, issues):
    # type: (Sequence[proto.tracker_pb2.Issue]) ->
    #     Sequence[api_proto.issue_objects_pb2.Issue]
    """Convert protorpc Issues into protoc Issues."""
    issue_ids = [issue.issue_id for issue in issues]
    issue_names_dict = rnc.ConvertIssueNames(
        self.cnxn, issue_ids, self.services)
    found_issues = [
        issue for issue in issues if issue.issue_id in issue_names_dict
    ]
    converted_issues = []
    for issue in found_issues:
      status = self._ConvertStatusValue(issue)
      content_state = issue_objects_pb2.IssueContentState.Value(
          'STATE_UNSPECIFIED')
      if issue.is_spam:
        content_state = issue_objects_pb2.IssueContentState.Value('SPAM')
      elif issue.deleted:
        content_state = issue_objects_pb2.IssueContentState.Value('DELETED')
      else:
        content_state = issue_objects_pb2.IssueContentState.Value('ACTIVE')

      owner = None
      # Explicit values override values derived from rules.
      if issue.owner_id:
        owner = issue_objects_pb2.Issue.UserValue(
            derivation=issue_objects_pb2.Derivation.Value('EXPLICIT'),
            user=rnc.ConvertUserName(issue.owner_id))
      elif issue.derived_owner_id:
        owner = issue_objects_pb2.Issue.UserValue(
            derivation=issue_objects_pb2.Derivation.Value('RULE'),
            user=rnc.ConvertUserName(issue.derived_owner_id))

      cc_users = []
      for cc_user_id in issue.cc_ids:
        cc_users.append(
            issue_objects_pb2.Issue.UserValue(
                derivation=issue_objects_pb2.Derivation.Value('EXPLICIT'),
                user=rnc.ConvertUserName(cc_user_id)))
      for derived_cc_user_id in issue.derived_cc_ids:
        cc_users.append(
            issue_objects_pb2.Issue.UserValue(
                derivation=issue_objects_pb2.Derivation.Value('RULE'),
                user=rnc.ConvertUserName(derived_cc_user_id)))

      labels = self.ConvertLabels(
          issue.labels, issue.derived_labels, issue.project_id)
      components = self._ConvertComponentValues(issue)
      non_approval_fvs = self._GetNonApprovalFieldValues(
          issue.field_values, issue.project_id)
      field_values = self.ConvertFieldValues(
          non_approval_fvs, issue.project_id, issue.phases)
      field_values.extend(
          self.ConvertEnumFieldValues(
              issue.labels, issue.derived_labels, issue.project_id))
      related_issue_ids = (
          [issue.merged_into] + issue.blocked_on_iids + issue.blocking_iids)
      issue_names_by_ids = rnc.ConvertIssueNames(
          self.cnxn, related_issue_ids, self.services)
      merged_into_issue_ref = None
      if issue.merged_into and issue.merged_into in issue_names_by_ids:
        merged_into_issue_ref = issue_objects_pb2.IssueRef(
            issue=issue_names_by_ids[issue.merged_into])
      if issue.merged_into_external:
        merged_into_issue_ref = issue_objects_pb2.IssueRef(
            ext_identifier=issue.merged_into_external)

      blocked_on_issue_refs = [
          issue_objects_pb2.IssueRef(issue=issue_names_by_ids[iid])
          for iid in issue.blocked_on_iids
          if iid in issue_names_by_ids
      ]
      blocked_on_issue_refs.extend(
          issue_objects_pb2.IssueRef(
              ext_identifier=blocked_on.ext_issue_identifier)
          for blocked_on in issue.dangling_blocked_on_refs)

      blocking_issue_refs = [
          issue_objects_pb2.IssueRef(issue=issue_names_by_ids[iid])
          for iid in issue.blocking_iids
          if iid in issue_names_by_ids
      ]
      blocking_issue_refs.extend(
          issue_objects_pb2.IssueRef(
              ext_identifier=blocking.ext_issue_identifier)
          for blocking in issue.dangling_blocking_refs)
      # All other timestamps were set when the issue was created.
      close_time = None
      if issue.closed_timestamp:
        close_time = timestamp_pb2.Timestamp(seconds=issue.closed_timestamp)

      phases = self._ComputePhases(issue.phases)

      result = issue_objects_pb2.Issue(
          name=issue_names_dict[issue.issue_id],
          summary=issue.summary,
          state=content_state,
          status=status,
          reporter=rnc.ConvertUserName(issue.reporter_id),
          owner=owner,
          cc_users=cc_users,
          labels=labels,
          components=components,
          field_values=field_values,
          merged_into_issue_ref=merged_into_issue_ref,
          blocked_on_issue_refs=blocked_on_issue_refs,
          blocking_issue_refs=blocking_issue_refs,
          create_time=timestamp_pb2.Timestamp(seconds=issue.opened_timestamp),
          close_time=close_time,
          modify_time=timestamp_pb2.Timestamp(seconds=issue.modified_timestamp),
          component_modify_time=timestamp_pb2.Timestamp(
              seconds=issue.component_modified_timestamp),
          status_modify_time=timestamp_pb2.Timestamp(
              seconds=issue.status_modified_timestamp),
          owner_modify_time=timestamp_pb2.Timestamp(
              seconds=issue.owner_modified_timestamp),
          star_count=issue.star_count,
          phases=phases)
      # TODO(crbug.com/monorail/5857): Set attachment_count unconditionally
      # after the underlying source of negative attachment counts has been
      # resolved and database has been repaired.
      if issue.attachment_count >= 0:
        result.attachment_count = issue.attachment_count
      converted_issues.append(result)
    return converted_issues

  def IngestAttachmentUploads(self, attachment_uploads):
    # type: (Sequence[api_proto.issues_pb2.AttachmentUpload] ->
    #     Sequence[framework_helpers.AttachmentUpload])
    """Ingests protoc AttachmentUploads into framework_helpers.AttachUploads."""
    ingested_uploads = []
    with exceptions.ErrorAggregator(exceptions.InputException) as err_agg:
      for up in attachment_uploads:
        if not up.filename or not up.content:
          err_agg.AddErrorMessage(
              'Uploaded atachment missing filename or content')
        mimetype = filecontent.GuessContentTypeFromFilename(up.filename)
        ingested_uploads.append(
            framework_helpers.AttachmentUpload(
                up.filename, up.content, mimetype))

    return ingested_uploads

  def IngestIssueDeltas(self, issue_deltas):
    # type: (Sequence[api_proto.issues_pb2.IssueDelta]) ->
    #     Sequence[Tuple[int, proto.tracker_pb2.IssueDelta]]
    """Ingests protoc IssueDeltas, into protorpc IssueDeltas.

    Args:
      issue_deltas: the protoc IssueDeltas to ingest.

    Returns:
      A list of (issue_id, tracker_pb2.IssueDelta) tuples that contain
      values found in issue_deltas, ignoring all OUTPUT_ONLY and masked
      fields.

    Raises:
      InputException: if any fields in the approval_deltas were invalid.
      NoSuchProjectException: if any parent projects are not found.
      NoSuchIssueException: if any issues are not found.
      NoSuchComponentException: if any components are not found.
    """
    issue_names = [delta.issue.name for delta in issue_deltas]
    issue_ids = rnc.IngestIssueNames(self.cnxn, issue_names, self.services)
    issues_dict, misses = self.services.issue.GetIssuesDict(
        self.cnxn, issue_ids)
    if misses:
      logging.info(
          'Issues not found for supposedly valid issue_ids: %r' % misses)
      raise ValueError('Could not fetch some issues.')
    configs_by_pid = self.services.config.GetProjectConfigs(
        self.cnxn, {issue.project_id for issue in issues_dict.values()})

    with exceptions.ErrorAggregator(exceptions.InputException) as err_agg:
      for api_delta in issue_deltas:
        if not api_delta.HasField('update_mask'):
          err_agg.AddErrorMessage(
              '`update_mask` must be set for {} delta.', api_delta.issue.name)
        elif not api_delta.update_mask.IsValidForDescriptor(
            issue_objects_pb2.Issue.DESCRIPTOR):
          err_agg.AddErrorMessage(
              'Invalid `update_mask` for {} delta.', api_delta.issue.name)

    ingested = []
    for iid, api_delta in zip(issue_ids, issue_deltas):
      delta = tracker_pb2.IssueDelta()

      # Check non-repeated fields before MergeMessage because in an object
      # where fields are not set and with a FieldMask applied, there is no
      # way to tell if empty fields were explicitly listed or not listed
      # in the FieldMask.
      paths_set = set(api_delta.update_mask.paths)
      if (not paths_set.isdisjoint({'status', 'status.status'}) and
          api_delta.issue.status.status):
        delta.status = api_delta.issue.status.status
      elif 'status.status' in paths_set and not api_delta.issue.status.status:
        delta.status = ''

      if (not paths_set.isdisjoint({'owner', 'owner.user'}) and
          api_delta.issue.owner.user):
        delta.owner_id = rnc.IngestUserName(
              self.cnxn, api_delta.issue.owner.user, self.services)
      elif 'owner.user' in paths_set and not api_delta.issue.owner.user:
        delta.owner_id = framework_constants.NO_USER_SPECIFIED

      if 'summary' in paths_set:
        if api_delta.issue.summary:
          delta.summary = api_delta.issue.summary
        else:
          delta.summary = ''

      merge_ref = api_delta.issue.merged_into_issue_ref
      if 'merged_into_issue_ref' in paths_set:
        if (api_delta.issue.merged_into_issue_ref.issue or
            api_delta.issue.merged_into_issue_ref.ext_identifier):
          ingested_ref = self._IngestIssueRef(merge_ref)
          if isinstance(ingested_ref, tracker_pb2.DanglingIssueRef):
            delta.merged_into_external = ingested_ref.ext_issue_identifier
          else:
            delta.merged_into = ingested_ref
      elif 'merged_into_issue_ref.issue' in paths_set:
        if api_delta.issue.merged_into_issue_ref.issue:
          delta.merged_into = self._IngestIssueRef(merge_ref)
        else:
          delta.merged_into = 0
      elif 'merged_into_issue_ref.ext_identifier' in paths_set:
        if api_delta.issue.merged_into_issue_ref.ext_identifier:
          ingested_ref = self._IngestIssueRef(merge_ref)
          delta.merged_into_external = ingested_ref.ext_issue_identifier
        else:
          delta.merged_into_external = ''

      filtered_api_issue = issue_objects_pb2.Issue()
      api_delta.update_mask.MergeMessage(
          api_delta.issue,
          filtered_api_issue,
          replace_message_field=True,
          replace_repeated_field=True)

      cc_names = [name for name in api_delta.ccs_remove] + [
          user_value.user for user_value in filtered_api_issue.cc_users
      ]
      cc_ids = rnc.IngestUserNames(self.cnxn, cc_names, self.services)
      delta.cc_ids_remove = cc_ids[:len(api_delta.ccs_remove)]
      delta.cc_ids_add = cc_ids[len(api_delta.ccs_remove):]

      comp_names = [component for component in api_delta.components_remove] + [
          c_value.component for c_value in filtered_api_issue.components
      ]
      project_comp_ids = rnc.IngestComponentDefNames(
          self.cnxn, comp_names, self.services)
      comp_ids = [comp_id for (_pid, comp_id) in project_comp_ids]
      delta.comp_ids_remove = comp_ids[:len(api_delta.components_remove)]
      delta.comp_ids_add = comp_ids[len(api_delta.components_remove):]

      # Added to delta below, after ShiftEnumFieldsIntoLabels.
      labels_add = [value.label for value in filtered_api_issue.labels]
      labels_remove = [label for label in api_delta.labels_remove]

      config = configs_by_pid[issues_dict[iid].project_id]
      fvs_add, add_enums = self._IngestFieldValues(
          filtered_api_issue.field_values, config)
      fvs_remove, remove_enums = self._IngestFieldValues(
          api_delta.field_vals_remove, config)
      field_helpers.ShiftEnumFieldsIntoLabels(
          labels_add, labels_remove, add_enums, remove_enums, config)
      delta.field_vals_add = fvs_add
      delta.field_vals_remove = fvs_remove
      delta.labels_add = labels_add
      delta.labels_remove = labels_remove
      assert len(add_enums) == 0  # ShiftEnumFieldsIntoLabels clears all enums.
      assert len(remove_enums) == 0

      blocked_on_iids_rm, blocked_on_dangling_rm = self._IngestIssueRefs(
          api_delta.blocked_on_issues_remove)
      delta.blocked_on_remove = blocked_on_iids_rm
      delta.ext_blocked_on_remove = [
          ref.ext_issue_identifier for ref in blocked_on_dangling_rm
      ]

      blocked_on_iids_add, blocked_on_dangling_add = self._IngestIssueRefs(
          filtered_api_issue.blocked_on_issue_refs)
      delta.blocked_on_add = blocked_on_iids_add
      delta.ext_blocked_on_add = [
          ref.ext_issue_identifier for ref in blocked_on_dangling_add
      ]

      blocking_iids_rm, blocking_dangling_rm = self._IngestIssueRefs(
          api_delta.blocking_issues_remove)
      delta.blocking_remove = blocking_iids_rm
      delta.ext_blocking_remove = [
          ref.ext_issue_identifier for ref in blocking_dangling_rm
      ]

      blocking_iids_add, blocking_dangling_add = self._IngestIssueRefs(
          filtered_api_issue.blocking_issue_refs)
      delta.blocking_add = blocking_iids_add
      delta.ext_blocking_add = [
          ref.ext_issue_identifier for ref in blocking_dangling_add
      ]

      ingested.append((iid, delta))

    return ingested

  def IngestApprovalDeltas(self, approval_deltas, setter_id):
    # type: (Sequence[api_proto.issues_pb2.ApprovalDelta], int) ->
    #     Sequence[Tuple[int, int, proto.tracker_pb2.ApprovalDelta]]
    """Ingests protoc ApprovalDeltas into protorpc ApprovalDeltas.

    Args:
      approval_deltas: the protoc ApprovalDeltas to ingest.
      setter_id: The ID for the user setting the deltas.

    Returns:
      Sequence of (issue_id, approval_id, ApprovalDelta) tuples in the order
      provided. The ApprovalDeltas ignore all OUTPUT_ONLY and masked fields.
      The tuples are "delta_specifications;" they identify one requested change.

    Raises:
      InputException: if any fields in the approval_delta protos were invalid.
      NoSuchProjectException: if the parent project of any ApprovalValue isn't
          found.
      NoSuchIssueException: if the issue of any ApprovalValue isn't found.
      NoSuchUserException: if any user value was provided with an invalid email.
          Note that users specified by ID are not checked for existence.
    """
    delta_specifications = []
    set_on = int(time.time())  # Use the same timestamp for all deltas.
    for approval_delta in approval_deltas:
      approval_name = approval_delta.approval_value.name
      # TODO(crbug/monorail/8173): Aggregate errors.
      project_id, issue_id, approval_id = rnc.IngestApprovalValueName(
          self.cnxn, approval_name, self.services)

      if not approval_delta.HasField('update_mask'):
        raise exceptions.InputException(
            '`update_mask` must be set for %s delta.' % approval_name)
      elif not approval_delta.update_mask.IsValidForDescriptor(
          issue_objects_pb2.ApprovalValue.DESCRIPTOR):
        raise exceptions.InputException(
            'Invalid `update_mask` for %s delta.' % approval_name)
      filtered_value = issue_objects_pb2.ApprovalValue()
      approval_delta.update_mask.MergeMessage(
          approval_delta.approval_value,
          filtered_value,
          replace_message_field=True,
          replace_repeated_field=True)
      status = _APPROVAL_STATUS_INGEST[filtered_value.status]
      # Approvers
      # No autocreate.
      # A user may try to remove all existing approvers [a, b] and add another
      # approver [c]. If they mis-type `c` and we auto-create `c` instead of
      # raising error, this would cause the ApprovalValue to be editable by no
      # one but site admins.
      approver_ids_add = rnc.IngestUserNames(
          self.cnxn, filtered_value.approvers, self.services, autocreate=False)
      approver_ids_remove = rnc.IngestUserNames(
          self.cnxn,
          approval_delta.approvers_remove,
          self.services,
          autocreate=False)

      # Field Values.
      config = self.services.config.GetProjectConfig(self.cnxn, project_id)
      approval_fds_by_id = {
          fd.field_id: fd
          for fd in config.field_defs
          if fd.field_type is tracker_pb2.FieldTypes.APPROVAL_TYPE
      }
      if approval_id not in approval_fds_by_id:
        raise exceptions.InputException(
            'Approval not found in project for %s' % approval_name)

      sub_fvs_add, add_enums = self._IngestFieldValues(
          filtered_value.field_values, config, approval_id_filter=approval_id)
      sub_fvs_remove, remove_enums = self._IngestFieldValues(
          approval_delta.field_vals_remove,
          config,
          approval_id_filter=approval_id)
      labels_add = []
      labels_remove = []
      field_helpers.ShiftEnumFieldsIntoLabels(
          labels_add, labels_remove, add_enums, remove_enums, config)
      assert len(add_enums) == 0  # ShiftEnumFieldsIntoLabels clears all enums.
      assert len(remove_enums) == 0
      delta = tbo.MakeApprovalDelta(
          status,
          setter_id,
          approver_ids_add,
          approver_ids_remove,
          sub_fvs_add,
          sub_fvs_remove, [],
          labels_add,
          labels_remove,
          set_on=set_on)
      delta_specifications.append((issue_id, approval_id, delta))
    return delta_specifications

  def IngestIssue(self, issue, project_id):
    # type: (api_proto.issue_objects_pb2.Issue, int) -> proto.tracker_pb2.Issue
    """Ingest a protoc Issue into a protorpc Issue.

    Args:
      issue: the protoc issue to ingest.
      project_id: The project into which we're ingesting `issue`.

    Returns:
      protorpc version of issue, ignoring all OUTPUT_ONLY fields.

    Raises:
      InputException: if any fields in the 'issue' proto were invalid.
      NoSuchProjectException: if 'project_id' is not found.
    """
    # Get config first. We can't ingest the issue if the project isn't found.
    config = self.services.config.GetProjectConfig(self.cnxn, project_id)
    ingestedDict = {
      'project_id': project_id,
      'summary': issue.summary
    }
    with exceptions.ErrorAggregator(exceptions.InputException) as err_agg:
      self._ExtractOwner(issue, ingestedDict, err_agg)

      # Extract ccs.
      try:
        ingestedDict['cc_ids'] = rnc.IngestUserNames(
            self.cnxn, [cc.user for cc in issue.cc_users], self.services,
            autocreate=True)
      except exceptions.InputException as e:
        err_agg.AddErrorMessage('Error ingesting cc_users: {}', e)

      # Extract status.
      if issue.HasField('status') and issue.status.status:
        ingestedDict['status'] = issue.status.status
      else:
        err_agg.AddErrorMessage('Status is required when creating an issue')

      # Extract components.
      try:
        project_comp_ids = rnc.IngestComponentDefNames(
            self.cnxn, [cv.component for cv in issue.components], self.services)
        ingestedDict['component_ids'] = [
            comp_id for (_pid, comp_id) in project_comp_ids]
      except (exceptions.InputException, exceptions.NoSuchProjectException,
              exceptions.NoSuchComponentException) as e:
        err_agg.AddErrorMessage('Error ingesting components: {}', e)

      # Extract labels and field values.
      ingestedDict['labels'] = [lv.label for lv in issue.labels]
      try:
        ingestedDict['field_values'], enums = self._IngestFieldValues(
            issue.field_values, config)
        field_helpers.ShiftEnumFieldsIntoLabels(
            ingestedDict['labels'], [], enums, [], config)
        assert len(
            enums) == 0  # ShiftEnumFieldsIntoLabels must clear all enums.
      except exceptions.InputException as e:
        err_agg.AddErrorMessage(e.message)

      # Ingest merged, blocking/blocked_on.
      self._ExtractIssueRefs(issue, ingestedDict, err_agg)
    return tracker_pb2.Issue(**ingestedDict)

  def _IngestFieldValues(self, field_values, config, approval_id_filter=None):
    # type: (Sequence[api_proto.issue_objects.FieldValue],
    #     proto.tracker_pb2.ProjectIssueConfig, Optional[int]) ->
    #     Tuple[Sequence[proto.tracker_pb2.FieldValue],
    #         Mapping[int, Sequence[str]]]
    """Returns protorpc FieldValues for the given protoc FieldValues.

    Raises exceptions if any field could not be parsed for any reasons such as
        unsupported field type, non-existent field, field from different
        projects, or fields with mismatched parent approvals.

    Args:
      field_values: protoc FieldValues to ingest.
      config: ProjectIssueConfig for the FieldValues we're ingesting.
      approval_id_filter: an approval_id, including any FieldValues that does
          not have this approval as a parent will trigger InputException.

    Returns:
      A pair 1) Ingested FieldValues. 2) A mapping of field ids to values
      for ENUM_TYPE fields in 'field_values.'

    Raises:
      InputException: if any fields_values could not be parsed for any reasons
          such as unsupported field type, non-existent field, or field from
          different projects.
    """
    fds_by_id = {fd.field_id: fd for fd in config.field_defs}
    enums = {}
    ingestedFieldValues = []
    with exceptions.ErrorAggregator(exceptions.InputException) as err_agg:
      for fv in field_values:
        try:
          project_id, fd_id = rnc.IngestFieldDefName(
              self.cnxn, fv.field, self.services)
          fd = fds_by_id[fd_id]
          # Raise if field does not belong to approval_id_filter (if provided).
          if (approval_id_filter is not None and
              fd.approval_id != approval_id_filter):
            approval_name = rnc.ConvertApprovalDefNames(
                self.cnxn, [approval_id_filter], project_id,
                self.services)[approval_id_filter]
            err_agg.AddErrorMessage(
                'Field {} does not belong to approval {}', fv.field,
                approval_name)
            continue
          if fd.field_type == tracker_pb2.FieldTypes.ENUM_TYPE:
            enums.setdefault(fd_id, []).append(fv.value)
          else:
            ingestedFieldValues.append(self._IngestFieldValue(fv, fd))
        except (exceptions.InputException, exceptions.NoSuchProjectException,
                exceptions.NoSuchFieldDefException, ValueError) as e:
          err_agg.AddErrorMessage(
              'Could not ingest value ({}) for FieldDef ({}): {}', fv.value,
              fv.field, e)
        except exceptions.NoSuchUserException as e:
          err_agg.AddErrorMessage(
              'User ({}) not found when ingesting user field: {}', fv.value,
              fv.field)
        except KeyError as e:
          err_agg.AddErrorMessage('Field {} is not in this project', fv.field)
    return ingestedFieldValues, enums

  def _IngestFieldValue(self, field_value, field_def):
    # type: (api_proto.issue_objects.FieldValue, proto.tracker_pb2.FieldDef) ->
    #     proto.tracker_pb2.FieldValue
    """Ingest a protoc FieldValue into a protorpc FieldValue.

    Args:
      field_value: protoc FieldValue to ingest.
      field_def: protorpc FieldDef associated with 'field_value'.
          BOOL_TYPE and APPROVAL_TYPE are ignored.
          Enum values are not allowed. They must be ingested as labels.

    Returns:
      Ingested protorpc FieldValue.

    Raises:
      InputException if 'field_def' is USER_TYPE and 'field_value' does not
          have a valid formatted resource name.
      NoSuchUserException if specified user in field does not exist.
      ValueError if 'field_value' could not be parsed for 'field_def'.
    """
    assert field_def.field_type != tracker_pb2.FieldTypes.ENUM_TYPE
    if field_def.field_type == tracker_pb2.FieldTypes.USER_TYPE:
      return self._ParseOneUserFieldValue(field_value.value, field_def.field_id)
    fv = field_helpers.ParseOneFieldValue(
        self.cnxn, self.services.user, field_def, field_value.value)
    # ParseOneFieldValue currently ignores parsing errors, although it has TODOs
    # to raise them.
    if not fv:
      raise ValueError('Could not parse %s' % field_value.value)
    return fv

  def _ParseOneUserFieldValue(self, value, field_id):
    # type: (str, int) -> proto.tracker_pb2.FieldValue
    """Replacement for the obsolete user parsing in ParseOneFieldValue."""
    user_id = rnc.IngestUserName(self.cnxn, value, self.services)
    return tbo.MakeFieldValue(field_id, None, None, user_id, None, None, False)

  def _ExtractOwner(self, issue, ingestedDict, err_agg):
    # type: (api_proto.issue_objects_pb2.Issue, Dict[str, Any], ErrorAggregator)
    #     -> None
    """Fills 'owner' into `ingestedDict`, if it can be extracted."""
    if issue.HasField('owner'):
      try:
        # Unlike for cc's, we require owner be an existing user, thus call we
        # do not autocreate.
        ingestedDict['owner_id'] = rnc.IngestUserName(
            self.cnxn, issue.owner.user, self.services, autocreate=False)
      except exceptions.InputException as e:
        err_agg.AddErrorMessage(
            'Error ingesting owner ({}): {}', issue.owner.user, e)
      except exceptions.NoSuchUserException as e:
        err_agg.AddErrorMessage(
            'User ({}) not found when ingesting owner', e)
    else:
      ingestedDict['owner_id'] = framework_constants.NO_USER_SPECIFIED

  def _ExtractIssueRefs(self, issue, ingestedDict, err_agg):
    # type: (api_proto.issue_objects_pb2.Issue, Dict[str, Any], ErrorAggregator)
    #     -> None
    """Fills issue relationships into `ingestedDict` from `issue`."""
    if issue.HasField('merged_into_issue_ref'):
      try:
        merged_into_ref = self._IngestIssueRef(issue.merged_into_issue_ref)
        if isinstance(merged_into_ref, tracker_pb2.DanglingIssueRef):
          ingestedDict['merged_into_external'] = (
              merged_into_ref.ext_issue_identifier)
        else:
          ingestedDict['merged_into'] = merged_into_ref
      except exceptions.InputException as e:
        err_agg.AddErrorMessage(
            'Error ingesting ref {}: {}', issue.merged_into_issue_ref, e)
    try:
      iids, dangling_refs = self._IngestIssueRefs(issue.blocked_on_issue_refs)
      ingestedDict['blocked_on_iids'] = iids
      ingestedDict['dangling_blocked_on_refs'] = dangling_refs
    except exceptions.InputException as e:
      err_agg.AddErrorMessage(e.message)
    try:
      iids, dangling_refs = self._IngestIssueRefs(issue.blocking_issue_refs)
      ingestedDict['blocking_iids'] = iids
      ingestedDict['dangling_blocking_refs'] = dangling_refs
    except exceptions.InputException as e:
      err_agg.AddErrorMessage(e.message)

  def _IngestIssueRefs(self, issue_refs):
    # type: (api_proto.issue_objects.IssueRf) ->
    #     Tuple[Sequence[int], Sequence[tracker_pb2.DanglingIssueRef]]
    """Given protoc IssueRefs, returns issue_ids and DanglingIssueRefs."""
    issue_ids = []
    external_refs = []
    with exceptions.ErrorAggregator(exceptions.InputException) as err_agg:
      for ref in issue_refs:
        try:
          ingested_ref = self._IngestIssueRef(ref)
          if isinstance(ingested_ref, tracker_pb2.DanglingIssueRef):
            external_refs.append(ingested_ref)
          else:
            issue_ids.append(ingested_ref)
        except (exceptions.InputException, exceptions.NoSuchIssueException,
                exceptions.NoSuchProjectException) as e:
          err_agg.AddErrorMessage('Error ingesting ref {}: {}', ref, e)

    return issue_ids, external_refs

  def _IngestIssueRef(self, issue_ref):
    # type: (api_proto.issue_objects.IssueRef) ->
    #     Union[int, tracker_pb2.DanglingIssueRef]
    """Given a protoc IssueRef, returns an issue id or DanglingIssueRef."""
    if issue_ref.issue and issue_ref.ext_identifier:
      raise exceptions.InputException(
        'IssueRefs MUST NOT have both `issue` and `ext_identifier`')
    if issue_ref.issue:
      return rnc.IngestIssueName(self.cnxn, issue_ref.issue, self.services)
    if issue_ref.ext_identifier:
      # TODO(crbug.com/monorail/7208): Handle ingestion/conversion of CodeSite
      # refs. We may be able to avoid ever needing to ingest them.
      return tracker_pb2.DanglingIssueRef(
          ext_issue_identifier=issue_ref.ext_identifier
        )
    raise exceptions.InputException(
        'IssueRefs MUST have one of `issue` and `ext_identifier`')

  def IngestIssuesListColumns(self, issues_list_columns):
    # type: (Sequence[proto.issue_objects_pb2.IssuesListColumn] -> str
    """Ingest a list of protoc IssueListColumns and returns a string."""
    return ' '.join([col.column for col in issues_list_columns])

  def _ComputeIssuesListColumns(self, columns):
    # type: (string) -> Sequence[api_proto.issue_objects_pb2.IssuesListColumn]
    """Convert string representation of columns to protoc IssuesListColumns"""
    return [
        issue_objects_pb2.IssuesListColumn(column=col)
        for col in columns.split()
    ]

  def IngestNotifyType(self, notify):
    # type: (issue_pb.NotifyType) -> bool
    """Ingest a NotifyType to boolean."""
    if (notify == issues_pb2.NotifyType.Value('NOTIFY_TYPE_UNSPECIFIED') or
        notify == issues_pb2.NotifyType.Value('EMAIL')):
      return True
    elif notify == issues_pb2.NotifyType.Value('NO_NOTIFICATION'):
      return False

  # Users

  def ConvertUser(self, user):
    # type: (protorpc.User) -> api_proto.user_objects_pb2.User
    """Convert a protorpc User into a protoc User.

    Args:
      user: protorpc User object.

    Returns:
      The protoc User object.
    """
    return self.ConvertUsers([user.user_id])[user.user_id]


  # TODO(crbug/monorail/7238): Make this take in a full User object and
  # return a Sequence, rather than a map, after hotlist users are converted.
  def ConvertUsers(self, user_ids):
    # type: (Sequence[int]) -> Map(int, api_proto.user_objects_pb2.User)
    """Convert list of protorpc Users into list of protoc Users.

    Args:
      user_ids: List of User IDs.

    Returns:
      Dict of User IDs to User protos for given user_ids that could be found.
    """
    user_ids_to_names = {}

    # Get display names
    users_by_id = self.services.user.GetUsersByIDs(self.cnxn, user_ids)
    (display_names_by_id,
     display_emails_by_id) = framework_bizobj.CreateUserDisplayNamesAndEmails(
         self.cnxn, self.services, self.user_auth, users_by_id.values())

    for user_id, user in users_by_id.items():
      name = rnc.ConvertUserNames([user_id]).get(user_id)

      display_name = display_names_by_id.get(user_id)
      display_email = display_emails_by_id.get(user_id)
      availability = framework_helpers.GetUserAvailability(user)
      availability_message, _availability_status = availability

      user_ids_to_names[user_id] = user_objects_pb2.User(
          name=name,
          display_name=display_name,
          email=display_email,
          availability_message=availability_message)

    return user_ids_to_names

  def ConvertProjectStars(self, user_id, projects):
    # type: (int, Collection[protorpc.Project]) ->
    #     Collection[api_proto.user_objects_pb2.ProjectStar]
    """Convert list of protorpc Projects into protoc ProjectStars.

    Args:
      user_id: The user the ProjectStar is associated with.
      projects: All starred projects.

    Returns:
      List of ProjectStar messages.
    """
    api_project_stars = []
    for proj in projects:
      name = rnc.ConvertProjectStarName(
          self.cnxn, user_id, proj.project_id, self.services)
      star = user_objects_pb2.ProjectStar(name=name)
      api_project_stars.append(star)
    return api_project_stars

  # Field Defs

  def ConvertFieldDefs(self, field_defs, project_id):
    # type: (Sequence[proto.tracker_pb2.FieldDef], int) ->
    #     Sequence[api_proto.project_objects_pb2.FieldDef]
    """Convert sequence of protorpc FieldDefs to protoc FieldDefs.

    Args:
      field_defs: List of protorpc FieldDefs
      project_id: ID of the Project that is ancestor to all given
        `field_defs`.

    Returns:
      Sequence of protoc FieldDef in the same order they are given in
      `field_defs`. In the event any field_def or the referenced approval_id
      in `field_defs` is not found, they will be omitted from the result.
    """
    field_ids = [fd.field_id for fd in field_defs]
    resource_names_dict = rnc.ConvertFieldDefNames(
        self.cnxn, field_ids, project_id, self.services)
    parent_approval_ids = [
        fd.approval_id for fd in field_defs if fd.approval_id is not None
    ]
    approval_names_dict = rnc.ConvertApprovalDefNames(
        self.cnxn, parent_approval_ids, project_id, self.services)

    api_fds = []
    for fd in field_defs:
      # Skip over approval fields, they have their separate ApprovalDef
      if fd.field_type == tracker_pb2.FieldTypes.APPROVAL_TYPE:
        continue
      if fd.field_id not in resource_names_dict:
        continue

      name = resource_names_dict.get(fd.field_id)
      display_name = fd.field_name
      docstring = fd.docstring
      field_type = self._ConvertFieldDefType(fd.field_type)
      applicable_issue_type = fd.applicable_type
      admins = rnc.ConvertUserNames(fd.admin_ids).values()
      editors = rnc.ConvertUserNames(fd.editor_ids).values()
      traits = self._ComputeFieldDefTraits(fd)
      approval_parent = approval_names_dict.get(fd.approval_id)

      enum_settings = None
      if field_type == project_objects_pb2.FieldDef.Type.Value('ENUM'):
        enum_settings = project_objects_pb2.FieldDef.EnumTypeSettings(
            choices=self._GetEnumFieldChoices(fd))

      int_settings = None
      if field_type == project_objects_pb2.FieldDef.Type.Value('INT'):
        int_settings = project_objects_pb2.FieldDef.IntTypeSettings(
            min_value=fd.min_value, max_value=fd.max_value)

      str_settings = None
      if field_type == project_objects_pb2.FieldDef.Type.Value('STR'):
        str_settings = project_objects_pb2.FieldDef.StrTypeSettings(
            regex=fd.regex)

      user_settings = None
      if field_type == project_objects_pb2.FieldDef.Type.Value('USER'):
        user_settings = project_objects_pb2.FieldDef.UserTypeSettings(
            role_requirements=self._ConvertRoleRequirements(fd.needs_member),
            notify_triggers=self._ConvertNotifyTriggers(fd.notify_on),
            grants_perm=fd.grants_perm,
            needs_perm=fd.needs_perm)

      date_settings = None
      if field_type == project_objects_pb2.FieldDef.Type.Value('DATE'):
        date_settings = project_objects_pb2.FieldDef.DateTypeSettings(
            date_action=self._ConvertDateAction(fd.date_action))

      api_fd = project_objects_pb2.FieldDef(
          name=name,
          display_name=display_name,
          docstring=docstring,
          type=field_type,
          applicable_issue_type=applicable_issue_type,
          admins=admins,
          traits=traits,
          approval_parent=approval_parent,
          enum_settings=enum_settings,
          int_settings=int_settings,
          str_settings=str_settings,
          user_settings=user_settings,
          date_settings=date_settings,
          editors=editors)
      api_fds.append(api_fd)
    return api_fds

  def _ConvertDateAction(self, date_action):
    # type: (proto.tracker_pb2.DateAction) ->
    #     api_proto.project_objects_pb2.FieldDef.DateTypeSettings.DateAction
    """Convert protorpc DateAction to protoc
       FieldDef.DateTypeSettings.DateAction"""
    if date_action == tracker_pb2.DateAction.NO_ACTION:
      return project_objects_pb2.FieldDef.DateTypeSettings.DateAction.Value(
          'NO_ACTION')
    elif date_action == tracker_pb2.DateAction.PING_OWNER_ONLY:
      return project_objects_pb2.FieldDef.DateTypeSettings.DateAction.Value(
          'NOTIFY_OWNER')
    elif date_action == tracker_pb2.DateAction.PING_PARTICIPANTS:
      return project_objects_pb2.FieldDef.DateTypeSettings.DateAction.Value(
          'NOTIFY_PARTICIPANTS')
    else:
      raise ValueError('Unsupported DateAction Value')

  def _ConvertRoleRequirements(self, needs_member):
    # type: (bool) ->
    #     api_proto.project_objects_pb2.FieldDef.
    #     UserTypeSettings.RoleRequirements
    """Convert protorpc RoleRequirements to protoc
       FieldDef.UserTypeSettings.RoleRequirements"""

    proto_user_settings = project_objects_pb2.FieldDef.UserTypeSettings
    if needs_member:
      return proto_user_settings.RoleRequirements.Value('PROJECT_MEMBER')
    else:
      return proto_user_settings.RoleRequirements.Value('NO_ROLE_REQUIREMENT')

  def _ConvertNotifyTriggers(self, notify_trigger):
    # type: (proto.tracker_pb2.NotifyTriggers) ->
    #     api_proto.project_objects_pb2.FieldDef.UserTypeSettings.NotifyTriggers
    """Convert protorpc NotifyTriggers to protoc
       FieldDef.UserTypeSettings.NotifyTriggers"""
    if notify_trigger == tracker_pb2.NotifyTriggers.NEVER:
      return project_objects_pb2.FieldDef.UserTypeSettings.NotifyTriggers.Value(
          'NEVER')
    elif notify_trigger == tracker_pb2.NotifyTriggers.ANY_COMMENT:
      return project_objects_pb2.FieldDef.UserTypeSettings.NotifyTriggers.Value(
          'ANY_COMMENT')
    else:
      raise ValueError('Unsupported NotifyTriggers Value')

  def _ConvertFieldDefType(self, field_type):
    # type: (proto.tracker_pb2.FieldTypes) ->
    #     api_proto.project_objects_pb2.FieldDef.Type
    """Convert protorpc FieldType to protoc FieldDef.Type

    Args:
      field_type: protorpc FieldType

    Returns:
      Corresponding protoc FieldDef.Type

    Raises:
      ValueError if input `field_type` has no suitable supported FieldDef.Type,
      or input `field_type` is not a recognized enum option.
    """
    if field_type == tracker_pb2.FieldTypes.ENUM_TYPE:
      return project_objects_pb2.FieldDef.Type.Value('ENUM')
    elif field_type == tracker_pb2.FieldTypes.INT_TYPE:
      return project_objects_pb2.FieldDef.Type.Value('INT')
    elif field_type == tracker_pb2.FieldTypes.STR_TYPE:
      return project_objects_pb2.FieldDef.Type.Value('STR')
    elif field_type == tracker_pb2.FieldTypes.USER_TYPE:
      return project_objects_pb2.FieldDef.Type.Value('USER')
    elif field_type == tracker_pb2.FieldTypes.DATE_TYPE:
      return project_objects_pb2.FieldDef.Type.Value('DATE')
    elif field_type == tracker_pb2.FieldTypes.URL_TYPE:
      return project_objects_pb2.FieldDef.Type.Value('URL')
    else:
      raise ValueError(
          'Unsupported tracker_pb2.FieldType enum. Boolean types '
          'are unsupported and approval types are found in ApprovalDefs')

  def _ComputeFieldDefTraits(self, field_def):
    # type: (proto.tracker_pb2.FieldDef) ->
    #     Sequence[api_proto.project_objects_pb2.FieldDef.Traits]
    """Compute sequence of FieldDef.Traits for a given protorpc FieldDef."""
    trait_protos = []
    if field_def.is_required:
      trait_protos.append(project_objects_pb2.FieldDef.Traits.Value('REQUIRED'))
    if field_def.is_niche:
      trait_protos.append(
          project_objects_pb2.FieldDef.Traits.Value('DEFAULT_HIDDEN'))
    if field_def.is_multivalued:
      trait_protos.append(
          project_objects_pb2.FieldDef.Traits.Value('MULTIVALUED'))
    if field_def.is_phase_field:
      trait_protos.append(project_objects_pb2.FieldDef.Traits.Value('PHASE'))
    if field_def.is_restricted_field:
      trait_protos.append(
          project_objects_pb2.FieldDef.Traits.Value('RESTRICTED'))
    return trait_protos

  def _GetEnumFieldChoices(self, field_def):
    # type: (proto.tracker_pb2.FieldDef) ->
    #     Sequence[Choice]
    """Get sequence of choices for an enum field

    Args:
      field_def: protorpc FieldDef

    Returns:
      Sequence of valid Choices for enum field `field_def`.

    Raises:
      ValueError if input `field_def` is not an enum type field.
    """
    if field_def.field_type != tracker_pb2.FieldTypes.ENUM_TYPE:
      raise ValueError('Cannot get value from label for non-enum-type field')

    config = self.services.config.GetProjectConfig(
        self.cnxn, field_def.project_id)
    value_docstr_tuples = tracker_helpers._GetEnumFieldValuesAndDocstrings(
        field_def, config)

    return [
        Choice(value=value, docstring=docstring)
        for value, docstring in value_docstr_tuples
    ]

  # Field Values

  def _GetNonApprovalFieldValues(self, field_values, project_id):
    # type: (Sequence[proto.tracker_pb2.FieldValue], int) ->
    #     Sequence[proto.tracker_pb2.FieldValue]
    """Filter out field values that belong to an approval field."""
    config = self.services.config.GetProjectConfig(self.cnxn, project_id)
    approval_fd_ids = set(
        [fd.field_id for fd in config.field_defs if fd.approval_id])

    return [fv for fv in field_values if fv.field_id not in approval_fd_ids]

  def ConvertFieldValues(self, field_values, project_id, phases):
    # type: (Sequence[proto.tracker_pb2.FieldValue], int,
    #     Sequence[proto.tracker_pb2.Phase]) ->
    #     Sequence[api_proto.issue_objects_pb2.FieldValue]
    """Convert sequence of field_values to protoc FieldValues.

    This method does not handle enum_type fields.

    Args:
      field_values: List of FieldValues
      project_id: ID of the Project that is ancestor to all given
        `field_values`.
      phases: List of Phases

    Returns:
      Sequence of protoc FieldValues in the same order they are given in
      `field_values`. In the event any field_values in `field_values` are not
      found, they will be omitted from the result.
    """
    phase_names_by_id = {phase.phase_id: phase.name for phase in phases}
    field_ids = [fv.field_id for fv in field_values]
    resource_names_dict = rnc.ConvertFieldDefNames(
        self.cnxn, field_ids, project_id, self.services)

    api_fvs = []
    for fv in field_values:
      if fv.field_id not in resource_names_dict:
        continue

      name = resource_names_dict.get(fv.field_id)
      value = self._ComputeFieldValueString(fv)
      derivation = self._ComputeFieldValueDerivation(fv)
      phase = phase_names_by_id.get(fv.phase_id)
      api_item = issue_objects_pb2.FieldValue(
          field=name, value=value, derivation=derivation, phase=phase)
      api_fvs.append(api_item)

    return api_fvs

  def _ComputeFieldValueString(self, field_value):
    # type: (proto.tracker_pb2.FieldValue) -> str
    """Convert a FieldValue's value to a string."""
    if field_value is None:
      raise exceptions.InputException('No FieldValue specified')
    elif field_value.int_value is not None:
      return str(field_value.int_value)
    elif field_value.str_value is not None:
      return field_value.str_value
    elif field_value.user_id is not None:
      return rnc.ConvertUserNames([field_value.user_id
                                  ]).get(field_value.user_id)
    elif field_value.date_value is not None:
      return str(field_value.date_value)
    elif field_value.url_value is not None:
      return field_value.url_value
    else:
      raise exceptions.InputException('FieldValue must have at least one value')

  def _ComputeFieldValueDerivation(self, field_value):
    # type: (proto.tracker_pb2.FieldValue) ->
    #     api_proto.issue_objects_pb2.Issue.Derivation
    """Convert a FieldValue's 'derived' to a protoc Issue.Derivation.

    Args:
      field_value: protorpc FieldValue

    Returns:
      Issue.Derivation of given `field_value`
    """
    if field_value.derived:
      return issue_objects_pb2.Derivation.Value('RULE')
    else:
      return issue_objects_pb2.Derivation.Value('EXPLICIT')

  # Approval Def

  def ConvertApprovalDefs(self, approval_defs, project_id):
    # type: (Sequence[proto.tracker_pb2.ApprovalDef], int) ->
    #     Sequence[api_proto.project_objects_pb2.ApprovalDef]
    """Convert sequence of protorpc ApprovalDefs to protoc ApprovalDefs.

    Args:
      approval_defs: List of protorpc ApprovalDefs
      project_id: ID of the Project the approval_defs belong to.

    Returns:
      Sequence of protoc ApprovalDefs in the same order they are given in
      in `approval_defs`. In the event any approval_def in `approval_defs`
      are not found, they will be omitted from the result.
    """
    approval_ids = set([ad.approval_id for ad in approval_defs])
    resource_names_dict = rnc.ConvertApprovalDefNames(
        self.cnxn, approval_ids, project_id, self.services)

    # Get matching field defs, needed to fill out protoc ApprovalDefs
    config = self.services.config.GetProjectConfig(self.cnxn, project_id)
    fd_by_id = {}
    for fd in config.field_defs:
      if (fd.field_type == tracker_pb2.FieldTypes.APPROVAL_TYPE and
          fd.field_id in approval_ids):
        fd_by_id[fd.field_id] = fd

    all_users = tbo.UsersInvolvedInApprovalDefs(
        approval_defs, fd_by_id.values())
    user_resource_names_dict = rnc.ConvertUserNames(all_users)

    api_ads = []
    for ad in approval_defs:
      if (ad.approval_id not in resource_names_dict or
          ad.approval_id not in fd_by_id):
        continue
      matching_fd = fd_by_id.get(ad.approval_id)
      name = resource_names_dict.get(ad.approval_id)
      display_name = matching_fd.field_name
      docstring = matching_fd.docstring
      survey = ad.survey
      approvers = [
          user_resource_names_dict.get(approver_id)
          for approver_id in ad.approver_ids
      ]
      admins = [
          user_resource_names_dict.get(admin_id)
          for admin_id in matching_fd.admin_ids
      ]

      api_ad = project_objects_pb2.ApprovalDef(
          name=name,
          display_name=display_name,
          docstring=docstring,
          survey=survey,
          approvers=approvers,
          admins=admins)
      api_ads.append(api_ad)
    return api_ads

  def ConvertApprovalValues(self, approval_values, field_values, phases,
                            issue_id=None, project_id=None):
    # type: (Sequence[proto.tracker_pb2.ApprovalValue],
    #     Sequence[proto.tracker_pb2.FieldValue],
    #     Sequence[proto.tracker_pb2.Phase], Optional[int], Optional[int]) ->
    #     Sequence[api_proto.issue_objects_pb2.ApprovalValue]
    """Convert sequence of approval_values to protoc ApprovalValues.

    `approval_values` may belong to a template or an issue. If they belong to a
    template, `project_id` should be given for the project the template is in.
    If these are issue `approval_values` `issue_id` should be given`.
    So, one of `issue_id` or `project_id` must be provided.
    If both are given, we ignore `project_id` and assume the `approval_values`
    belong to an issue.

    Args:
      approval_values: List of ApprovalValues.
      field_values: List of FieldValues that may belong to the approval_values.
      phases: List of Phases that may be associated with the approval_values.
      issue_id: ID of the Issue that the `approval_values` belong to.
      project_id: ID of the Project that the `approval_values`
        template belongs to.

    Returns:
      Sequence of protoc ApprovalValues in the same order they are given in
      in `approval_values`. In the event any approval definitions in
      `approval_values` are not found, they will be omitted from the result.

    Raises:
      InputException if neither `issue_id` nor `project_id` is given.
    """

    approval_ids = [av.approval_id for av in approval_values]
    resource_names_dict = {}
    if issue_id is not None:
      # Only issue approval_values have resource names.
      resource_names_dict = rnc.ConvertApprovalValueNames(
          self.cnxn, issue_id, self.services)
      project_id = self.services.issue.GetIssue(self.cnxn, issue_id).project_id
    elif project_id is None:
      raise exceptions.InputException(
          'One  `issue_id` or `project_id` must be given.')

    phase_names_by_id = {phase.phase_id: phase.name for phase in phases}
    ad_names_dict = rnc.ConvertApprovalDefNames(
        self.cnxn, approval_ids, project_id, self.services)

    # Organize the field values by the approval values they are
    # associated with.
    config = self.services.config.GetProjectConfig(self.cnxn, project_id)
    fds_by_id = {fd.field_id: fd for fd in config.field_defs}
    fvs_by_parent_approvals = collections.defaultdict(list)
    for fv in field_values:
      fd = fds_by_id.get(fv.field_id)
      if fd and fd.approval_id:
        fvs_by_parent_approvals[fd.approval_id].append(fv)

    api_avs = []
    for av in approval_values:
      # We only skip missing approval names if we are converting issue approval
      # values.
      if issue_id is not None and av.approval_id not in resource_names_dict:
        continue

      name = resource_names_dict.get(av.approval_id)
      approval_def = ad_names_dict.get(av.approval_id)
      approvers = rnc.ConvertUserNames(av.approver_ids).values()
      status = self._ComputeApprovalValueStatus(av.status)
      setter = rnc.ConvertUserName(av.setter_id)
      phase = phase_names_by_id.get(av.phase_id)

      field_values = self.ConvertFieldValues(
          fvs_by_parent_approvals[av.approval_id], project_id, phases)

      api_item = issue_objects_pb2.ApprovalValue(
          name=name,
          approval_def=approval_def,
          approvers=approvers,
          status=status,
          setter=setter,
          field_values=field_values,
          phase=phase)
      if av.set_on:
        api_item.set_time.FromSeconds(av.set_on)
      api_avs.append(api_item)

    return api_avs

  def _ComputeApprovalValueStatus(self, status):
    # type: (proto.tracker_pb2.ApprovalStatus) ->
    #     api_proto.issue_objects_pb2.Issue.ApprovalStatus
    """Convert a protorpc ApprovalStatus to a protoc Issue.ApprovalStatus."""
    try:
      return _APPROVAL_STATUS_CONVERT[status]
    except KeyError:
      raise ValueError('Unrecognized tracker_pb2.ApprovalStatus enum')

  # Projects

  def ConvertIssueTemplates(self, project_id, templates):
    # type: (int, Sequence[proto.tracker_pb2.TemplateDef]) ->
    #     Sequence[api_proto.project_objects_pb2.IssueTemplate]
    """Convert a Sequence of TemplateDefs to protoc IssueTemplates.

    Args:
      project_id: ID of the Project the templates belong to.
      templates: Sequence of TemplateDef protorpc objects.

    Returns:
      Sequence of protoc IssueTemplate in the same order they are given in
      `templates`. In the rare event that any templates are not found,
      they will be omitted from the result.
    """
    api_templates = []

    resource_names_dict = rnc.ConvertTemplateNames(
        self.cnxn, project_id, [template.template_id for template in templates],
        self.services)

    for template in templates:
      if template.template_id not in resource_names_dict:
        continue
      name = resource_names_dict.get(template.template_id)
      summary_must_be_edited = template.summary_must_be_edited
      template_privacy = self._ComputeTemplatePrivacy(template)
      default_owner = self._ComputeTemplateDefaultOwner(template)
      component_required = template.component_required
      admins = rnc.ConvertUserNames(template.admin_ids).values()
      issue = self._FillIssueFromTemplate(template, project_id)
      approval_values = self.ConvertApprovalValues(
          template.approval_values, template.field_values, template.phases,
          project_id=project_id)
      api_templates.append(
          project_objects_pb2.IssueTemplate(
              name=name,
              display_name=template.name,
              issue=issue,
              approval_values=approval_values,
              summary_must_be_edited=summary_must_be_edited,
              template_privacy=template_privacy,
              default_owner=default_owner,
              component_required=component_required,
              admins=admins))

    return api_templates

  def _FillIssueFromTemplate(self, template, project_id):
    # type: (proto.tracker_pb2.TemplateDef, int) ->
    #     api_proto.issue_objects_pb2.Issue
    """Convert a TemplateDef to its embedded protoc Issue.

    IssueTemplate does not set the following fields:
      name
      reporter
      cc_users
      blocked_on_issue_refs
      blocking_issue_refs
      create_time
      close_time
      modify_time
      component_modify_time
      status_modify_time
      owner_modify_time
      attachment_count
      star_count

    Args:
      template: TemplateDef protorpc objects.
      project_id: ID of the Project the template belongs to.

    Returns:
      protoc Issue filled with data from given `template`.
    """
    summary = template.summary
    state = issue_objects_pb2.IssueContentState.Value('ACTIVE')
    status = issue_objects_pb2.Issue.StatusValue(
        status=template.status,
        derivation=issue_objects_pb2.Derivation.Value('EXPLICIT'))
    owner = None
    if template.owner_id is not None:
      owner = issue_objects_pb2.Issue.UserValue(
          user=rnc.ConvertUserNames([template.owner_id]).get(template.owner_id))
    labels = self.ConvertLabels(template.labels, [], project_id)
    components_dict = rnc.ConvertComponentDefNames(
        self.cnxn, template.component_ids, project_id, self.services)
    components = []
    for component_resource_name in components_dict.values():
      components.append(
          issue_objects_pb2.Issue.ComponentValue(
              component=component_resource_name,
              derivation=issue_objects_pb2.Derivation.Value('EXPLICIT')))
    non_approval_fvs = self._GetNonApprovalFieldValues(
        template.field_values, project_id)
    field_values = self.ConvertFieldValues(
        non_approval_fvs, project_id, template.phases)
    field_values.extend(
        self.ConvertEnumFieldValues(template.labels, [], project_id))
    phases = self._ComputePhases(template.phases)

    filled_issue = issue_objects_pb2.Issue(
        summary=summary,
        state=state,
        status=status,
        owner=owner,
        labels=labels,
        components=components,
        field_values=field_values,
        phases=phases)
    return filled_issue

  def _ComputeTemplatePrivacy(self, template):
    # type: (proto.tracker_pb2.TemplateDef) ->
    #     api_proto.project_objects_pb2.IssueTemplate.TemplatePrivacy
    """Convert a protorpc TemplateDef to its protoc TemplatePrivacy."""
    if template.members_only:
      return project_objects_pb2.IssueTemplate.TemplatePrivacy.Value(
          'MEMBERS_ONLY')
    else:
      return project_objects_pb2.IssueTemplate.TemplatePrivacy.Value('PUBLIC')

  def _ComputeTemplateDefaultOwner(self, template):
    # type: (proto.tracker_pb2.TemplateDef) ->
    #     api_proto.project_objects_pb2.IssueTemplate.DefaultOwner
    """Convert a protorpc TemplateDef to its protoc DefaultOwner."""
    if template.owner_defaults_to_member:
      return project_objects_pb2.IssueTemplate.DefaultOwner.Value(
          'PROJECT_MEMBER_REPORTER')
    else:
      return project_objects_pb2.IssueTemplate.DefaultOwner.Value(
          'DEFAULT_OWNER_UNSPECIFIED')

  def _ComputePhases(self, phases):
    # type: (proto.tracker_pb2.TemplateDef) -> Sequence[str]
    """Convert a protorpc TemplateDef to its sorted string phases."""
    sorted_phases = sorted(phases, key=lambda phase: phase.rank)
    return [phase.name for phase in sorted_phases]

  def ConvertLabels(self, labels, derived_labels, project_id):
    # type: (Sequence[str], Sequence[str], int) ->
    #     Sequence[api_proto.issue_objects_pb2.Issue.LabelValue]
    """Convert string labels to LabelValues for non-enum-field labels

    Args:
      labels: Sequence of string labels
      project_id: ID of the Project these labels belong to.

    Return:
      Sequence of protoc IssueValues for given `labels` that
      do not represent enum field values.
    """
    config = self.services.config.GetProjectConfig(self.cnxn, project_id)
    non_fd_labels, non_fd_der_labels = tbo.ExplicitAndDerivedNonMaskedLabels(
        labels, derived_labels, config)
    api_labels = []
    for label in non_fd_labels:
      api_labels.append(
          issue_objects_pb2.Issue.LabelValue(
              label=label,
              derivation=issue_objects_pb2.Derivation.Value('EXPLICIT')))
    for label in non_fd_der_labels:
      api_labels.append(
          issue_objects_pb2.Issue.LabelValue(
              label=label,
              derivation=issue_objects_pb2.Derivation.Value('RULE')))
    return api_labels

  def ConvertEnumFieldValues(self, labels, derived_labels, project_id):
    # type: (Sequence[str], Sequence[str], int) ->
    #     Sequence[api_proto.issue_objects_pb2.FieldValue]
    """Convert string labels to FieldValues for enum-field labels

    Args:
      labels: Sequence of string labels
      project_id: ID of the Project these labels belong to.

    Return:
      Sequence of protoc FieldValues only for given `labels` that
      represent enum field values.
    """
    config = self.services.config.GetProjectConfig(self.cnxn, project_id)
    enum_ids_by_name = {
        fd.field_name.lower(): fd.field_id
        for fd in config.field_defs
        if fd.field_type is tracker_pb2.FieldTypes.ENUM_TYPE
        and not fd.is_deleted
    }
    resource_names_dict = rnc.ConvertFieldDefNames(
        self.cnxn, enum_ids_by_name.values(), project_id, self.services)

    api_fvs = []

    labels_by_prefix = tbo.LabelsByPrefix(labels, enum_ids_by_name.keys())
    for lower_field_name, values in labels_by_prefix.items():
      field_id = enum_ids_by_name.get(lower_field_name)
      resource_name = resource_names_dict.get(field_id)
      if not resource_name:
        continue
      api_fvs.extend(
          [
              issue_objects_pb2.FieldValue(
                  field=resource_name,
                  value=value,
                  derivation=issue_objects_pb2.Derivation.Value(
                      'EXPLICIT')) for value in values
          ])

    der_labels_by_prefix = tbo.LabelsByPrefix(
        derived_labels, enum_ids_by_name.keys())
    for lower_field_name, values in der_labels_by_prefix.items():
      field_id = enum_ids_by_name.get(lower_field_name)
      resource_name = resource_names_dict.get(field_id)
      if not resource_name:
        continue
      api_fvs.extend(
          [
              issue_objects_pb2.FieldValue(
                  field=resource_name,
                  value=value,
                  derivation=issue_objects_pb2.Derivation.Value('RULE'))
              for value in values
          ])

    return api_fvs

  def ConvertProject(self, project):
    # type: (proto.project_pb2.Project) ->
    #     api_proto.project_objects_pb2.Project
    """Convert a protorpc Project to its protoc Project."""

    return project_objects_pb2.Project(
        name=rnc.ConvertProjectName(
            self.cnxn, project.project_id, self.services),
        display_name=project.project_name,
        summary=project.summary,
        thumbnail_url=project_helpers.GetThumbnailUrl(project.logo_gcs_id))

  def ConvertProjects(self, projects):
    # type: (Sequence[proto.project_pb2.Project]) ->
    #     Sequence[api_proto.project_objects_pb2.Project]
    """Convert a Sequence of protorpc Projects to protoc Projects."""
    return [self.ConvertProject(proj) for proj in projects]

  def ConvertProjectConfig(self, project_config):
    # type: (proto.tracker_pb2.ProjectIssueConfig) ->
    #     api_proto.project_objects_pb2.ProjectConfig
    """Convert protorpc ProjectIssueConfig to protoc ProjectConfig."""
    project = self.services.project.GetProject(
        self.cnxn, project_config.project_id)
    project_grid_config = project_objects_pb2.ProjectConfig.GridViewConfig(
        default_x_attr=project_config.default_x_attr,
        default_y_attr=project_config.default_y_attr)
    template_names = rnc.ConvertTemplateNames(
        self.cnxn, project_config.project_id, [
            project_config.default_template_for_developers,
            project_config.default_template_for_users
        ], self.services)
    return project_objects_pb2.ProjectConfig(
        name=rnc.ConvertProjectConfigName(
            self.cnxn, project_config.project_id, self.services),
        exclusive_label_prefixes=project_config.exclusive_label_prefixes,
        member_default_query=project_config.member_default_query,
        default_sort=project_config.default_sort_spec,
        default_columns=self._ComputeIssuesListColumns(
            project_config.default_col_spec),
        project_grid_config=project_grid_config,
        member_default_template=template_names.get(
            project_config.default_template_for_developers),
        non_members_default_template=template_names.get(
            project_config.default_template_for_users),
        revision_url_format=project.revision_url_format,
        custom_issue_entry_url=project_config.custom_issue_entry_url)

  def CreateProjectMember(self, cnxn, project_id, user_id, role):
    # type: (MonorailContext, int, int, str) ->
    #     api_proto.project_objects_pb2.ProjectMember
    """Creates a ProjectMember object from specified parameters.

    Args:
      cnxn: MonorailConnection object.
      project_id: ID of the Project the User is a member of.
      user_id: ID of the user who is a member.
      role: str specifying the user's role based on a ProjectRole value.

    Return:
      A protoc ProjectMember object.
    """
    name = rnc.ConvertProjectMemberName(
        cnxn, project_id, user_id, self.services)
    return project_objects_pb2.ProjectMember(
        name=name,
        role=project_objects_pb2.ProjectMember.ProjectRole.Value(role))

  def ConvertLabelDefs(self, label_defs, project_id):
    # type: (Sequence[proto.tracker_pb2.LabelDef], int) ->
    #     Sequence[api_proto.project_objects_pb2.LabelDef]
    """Convert protorpc LabelDefs to protoc LabelDefs"""
    resource_names_dict = rnc.ConvertLabelDefNames(
        self.cnxn, [ld.label for ld in label_defs], project_id, self.services)

    api_lds = []
    for ld in label_defs:
      state = project_objects_pb2.LabelDef.LabelDefState.Value('ACTIVE')
      if ld.deprecated:
        state = project_objects_pb2.LabelDef.LabelDefState.Value('DEPRECATED')
      api_lds.append(
          project_objects_pb2.LabelDef(
              name=resource_names_dict.get(ld.label),
              value=ld.label,
              docstring=ld.label_docstring,
              state=state))
    return api_lds

  def ConvertStatusDefs(self, status_defs, project_id):
    # type: (Sequence[proto.tracker_pb2.StatusDef], int) ->
    #     Sequence[api_proto.project_objects_pb2.StatusDef]
    """Convert protorpc StatusDefs to protoc StatusDefs

    Args:
      status_defs: Sequence of StatusDefs.
      project_id: ID of the Project these belong to.

    Returns:
      Sequence of protoc StatusDefs in the same order they are given in
      `status_defs`.
    """
    resource_names_dict = rnc.ConvertStatusDefNames(
        self.cnxn, [sd.status for sd in status_defs], project_id, self.services)
    config = self.services.config.GetProjectConfig(self.cnxn, project_id)
    mergeable_statuses = set(config.statuses_offer_merge)

    # Rank is only surfaced as positional value in well_known_statuses
    rank_by_status = {}
    for rank, sd in enumerate(config.well_known_statuses):
      rank_by_status[sd.status] = rank

    api_sds = []
    for sd in status_defs:
      state = project_objects_pb2.StatusDef.StatusDefState.Value('ACTIVE')
      if sd.deprecated:
        state = project_objects_pb2.StatusDef.StatusDefState.Value('DEPRECATED')

      if sd.means_open:
        status_type = project_objects_pb2.StatusDef.StatusDefType.Value('OPEN')
      else:
        if sd.status in mergeable_statuses:
          status_type = project_objects_pb2.StatusDef.StatusDefType.Value(
              'MERGED')
        else:
          status_type = project_objects_pb2.StatusDef.StatusDefType.Value(
              'CLOSED')

      api_sd = project_objects_pb2.StatusDef(
          name=resource_names_dict.get(sd.status),
          value=sd.status,
          type=status_type,
          rank=rank_by_status[sd.status],
          docstring=sd.status_docstring,
          state=state,
      )
      api_sds.append(api_sd)
    return api_sds

  def ConvertComponentDef(self, component_def):
    # type: (proto.tracker_pb2.ComponentDef) ->
    #     api_proto.project_objects.ComponentDef
    """Convert a protorpc ComponentDef to a protoc ComponentDef."""
    return self.ConvertComponentDefs([component_def],
                                     component_def.project_id)[0]

  def ConvertComponentDefs(self, component_defs, project_id):
    # type: (Sequence[proto.tracker_pb2.ComponentDef], int) ->
    #     Sequence[api_proto.project_objects.ComponentDef]
    """Convert sequence of protorpc ComponentDefs to protoc ComponentDefs

    Args:
      component_defs: Sequence of protoc ComponentDefs.
      project_id: ID of the Project these belong to.

    Returns:
      Sequence of protoc ComponentDefs in the same order they are given in
      `component_defs`.
    """
    resource_names_dict = rnc.ConvertComponentDefNames(
        self.cnxn, [cd.component_id for cd in component_defs], project_id,
        self.services)
    involved_user_ids = tbo.UsersInvolvedInComponents(component_defs)
    user_resource_names_dict = rnc.ConvertUserNames(involved_user_ids)

    all_label_ids = set()
    for cd in component_defs:
      all_label_ids.update(cd.label_ids)

    # If this becomes a performance issue, we should add bulk look up.
    labels_by_id = {
        label_id: self.services.config.LookupLabel(
            self.cnxn, project_id, label_id) for label_id in all_label_ids
    }

    api_cds = []
    for cd in component_defs:
      state = project_objects_pb2.ComponentDef.ComponentDefState.Value('ACTIVE')
      if cd.deprecated:
        state = project_objects_pb2.ComponentDef.ComponentDefState.Value(
            'DEPRECATED')

      api_cd = project_objects_pb2.ComponentDef(
          name=resource_names_dict.get(cd.component_id),
          value=cd.path,
          docstring=cd.docstring,
          state=state,
          admins=[
              user_resource_names_dict.get(admin_id)
              for admin_id in cd.admin_ids
          ],
          ccs=[user_resource_names_dict.get(cc_id) for cc_id in cd.cc_ids],
          creator=user_resource_names_dict.get(cd.creator_id),
          modifier=user_resource_names_dict.get(cd.modifier_id),
          create_time=timestamp_pb2.Timestamp(seconds=cd.created),
          modify_time=timestamp_pb2.Timestamp(seconds=cd.modified),
          labels=[labels_by_id[label_id] for label_id in cd.label_ids],
      )
      api_cds.append(api_cd)
    return api_cds

  def ConvertProjectSavedQueries(self, saved_queries, project_id):
    # type: (Sequence[proto.tracker_pb2.SavedQuery], int) ->
    #     Sequence(api_proto.project_objects.ProjectSavedQuery)
    """Convert sequence of protorpc SavedQueries to protoc ProjectSavedQueries

    Args:
      saved_queries: Sequence of SavedQueries.
      project_id: ID of the Project these belong to.

    Returns:
      Sequence of protoc ProjectSavedQueries in the same order they are given in
      `saved_queries`. In the event any items in `saved_queries` are not found
      or don't belong to the project, they will be omitted from the result.
    """
    resource_names_dict = rnc.ConvertProjectSavedQueryNames(
        self.cnxn, [sq.query_id for sq in saved_queries], project_id,
        self.services)
    api_psqs = []
    for sq in saved_queries:
      if sq.query_id not in resource_names_dict:
        continue

      # TODO(crbug/monorail/7756): Remove base_query_id, avoid confusions.
      # Until then we have to expand the query by including base_query_id.
      # base_query_id can only be in the set of DEFAULT_CANNED_QUERIES.
      if sq.base_query_id:
        query = '{} {}'.format(tbo.GetBuiltInQuery(sq.base_query_id), sq.query)
      else:
        query = sq.query

      api_psqs.append(
          project_objects_pb2.ProjectSavedQuery(
              name=resource_names_dict.get(sq.query_id),
              display_name=sq.name,
              query=query))
    return api_psqs
