package org.batfish.datamodel.tracking;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.batfish.datamodel.Prefix;
import org.batfish.datamodel.RoutingProtocol;

/**
 * Tracks whether a route with a particular prefix and optionally matching one of a set of protocols
 * is in the main RIB of a particular VRF.
 */
public final class TrackRoute implements TrackMethod {

  @Override
  public <R> R accept(GenericTrackMethodVisitor<R> visitor) {
    return visitor.visitTrackRoute(this);
  }

  /** The prefix a tracked route must have. */
  @JsonProperty(PROP_PREFIX)
  public @Nonnull Prefix getPrefix() {
    return _prefix;
  }

  /**
   * If empty, do not match protocols. Else the protocol of the route to be matched must be present
   * in the returned set.
   */
  @JsonIgnore
  public @Nonnull Set<RoutingProtocol> getProtocols() {
    return _protocols;
  }

  @JsonProperty(PROP_PROTOCOLS)
  private @Nonnull SortedSet<RoutingProtocol> getProtocolsSorted() {
    return ImmutableSortedSet.copyOf(_protocols);
  }

  /** The vrf whose main RIB should be checked for a tracked route. */
  @JsonProperty(PROP_VRF)
  public @Nonnull String getVrf() {
    return _vrf;
  }

  @Override
  public boolean equals(@Nullable Object o) {
    if (this == o) {
      return true;
    } else if (!(o instanceof TrackRoute)) {
      return false;
    }
    TrackRoute that = (TrackRoute) o;
    return _prefix.equals(that._prefix)
        && _protocols.equals(that._protocols)
        && _vrf.equals(that._vrf);
  }

  @Override
  public int hashCode() {
    return Objects.hash(_prefix, _protocols, _vrf);
  }

  static @Nonnull TrackRoute of(Prefix prefix, Set<RoutingProtocol> protocols, String vrf) {
    checkArgument(!Strings.isNullOrEmpty(vrf), "vrf name must be non-empty");
    return new TrackRoute(prefix, protocols, vrf);
  }

  @JsonCreator
  private static @Nonnull TrackRoute create(
      @JsonProperty(PROP_PREFIX) @Nullable Prefix prefix,
      @JsonProperty(PROP_PROTOCOLS) @Nullable Set<RoutingProtocol> protocols,
      @JsonProperty(PROP_VRF) @Nullable String vrf) {
    checkArgument(prefix != null, "Missing %s", PROP_PREFIX);
    checkArgument(vrf != null, "Missing %s", PROP_VRF);
    return new TrackRoute(
        prefix, ImmutableSet.copyOf(firstNonNull(protocols, ImmutableSet.of())), vrf);
  }

  private static final String PROP_PREFIX = "prefix";
  private static final String PROP_PROTOCOLS = "protocols";
  private static final String PROP_VRF = "vrf";

  private final @Nonnull Prefix _prefix;
  private final @Nonnull Set<RoutingProtocol> _protocols;
  private final @Nonnull String _vrf;

  private TrackRoute(Prefix prefix, Set<RoutingProtocol> protocols, String vrf) {
    _prefix = prefix;
    _protocols = protocols;
    _vrf = vrf;
  }
}

@@ -93,24 +93,89 @@
 rstNonNull;%0A
+import static com.google.common.base.MoreObjects.toStringHelper;%0A
 import stati
@@ -2912,16 +2912,220 @@
 );%0A  %7D%0A%0A
+  @Override%0A  public String toString() %7B%0A    return toStringHelper(this)%0A        .add(PROP_PREFIX, _prefix)%0A        .add(PROP_PROTOCOLS, _protocols)%0A        .add(PROP_VRF, _vrf)%0A        .toString();%0A  %7D%0A%0A
   privat

Add toString to TrackRoute (#8243)