class BgpSessionCompatibilityAnswerer extends Answerer {

  @Nonnull
  @VisibleForTesting
  static List<Row> getPassivePeerRows(
      BgpPeerConfigId passiveId,
      BgpPassivePeerConfig passivePeer,
      NetworkConfigurations nc,
      ValueGraph<BgpPeerConfigId, BgpSessionProperties> configuredTopology) {
    // Start row with base columns. Need to add status.
    // If there are compatible peers, will also add remote node and replace:
    // - local IP, with the remote node's remote IP
    // - remote AS
    // - remote IP
    // - session type
    // Local and remote interface will not be filled in (reserved for unnumbered peers).
    Row.TypedRowBuilder rb =
        Row.builder(METADATA_MAP)
            .put(COL_LOCAL_AS, passivePeer.getLocalAs())
            .put(COL_LOCAL_IP, passivePeer.getLocalIp())
            .put(COL_NODE, new Node(passiveId.getHostname()))
            .put(COL_REMOTE_AS, passivePeer.getRemoteAsns().toString())
            .put(
                COL_REMOTE_IP, new SelfDescribingObject(Schema.PREFIX, passivePeer.getPeerPrefix()))
            .put(COL_ADDRESS_FAMILIES, ImmutableSet.of())
            .put(COL_SESSION_TYPE, SessionType.UNSET)
            .put(COL_VRF, passiveId.getVrfName());

    // If peer has null remote prefix or empty remote AS list, generate one row
    ConfiguredSessionStatus brokenStatus = getLocallyBrokenStatus(passivePeer);
    if (brokenStatus != null) {
      return ImmutableList.of(rb.put(COL_CONFIGURED_STATUS, brokenStatus).build());
    }

    // Create a row for each valid remote peer compatible with this peer
    List<Row> rows =
        configuredTopology.adjacentNodes(passiveId).stream()
            // inDegree vs outDegree doesn't matter here, just need to make sure the remote isn't
            // compatible with any other peers
            .filter(remoteId -> configuredTopology.inDegree(remoteId) == 1)
            .map(
                remoteId -> {
                  BgpSessionProperties sessionProps =
                      configuredTopology.edgeValue(passiveId, remoteId).orElse(null);
                  assert sessionProps != null;
                  BgpActivePeerConfig activeRemote = nc.getBgpPointToPointPeerConfig(remoteId);
                  assert activeRemote != null;
                  return rb.put(COL_CONFIGURED_STATUS, DYNAMIC_MATCH)
                      .put(COL_ADDRESS_FAMILIES, sessionProps.getAddressFamilies())
                      .put(COL_LOCAL_IP, sessionProps.getTailIp())
                      .put(COL_LOCAL_AS, sessionProps.getTailAs())
                      .put(COL_REMOTE_AS, Long.toString(sessionProps.getHeadAs()))
                      .put(COL_REMOTE_NODE, new Node(remoteId.getHostname()))
                      .put(
                          COL_REMOTE_IP,
                          new SelfDescribingObject(Schema.IP, sessionProps.getHeadIp()))
                      .put(COL_SESSION_TYPE, getSessionType(activeRemote))
                      .build();
                })
            .collect(ImmutableList.toImmutableList());

    // If no compatible neighbors were found, generate one NO_MATCH_FOUND row
    return rows.isEmpty()
        ? ImmutableList.of(rb.put(COL_CONFIGURED_STATUS, NO_MATCH_FOUND).build())
        : rows;
  }

  public  BgpSessionCompatibilityAnswerer(Question question, IBatfish batfish);

}