@ToString
@EqualsAndHashCode(callSuper = true)
public class SearchAttractionsOperation extends PagedOperation<SearchAttractionsOperation> {

  public SearchAttractionsOperation keyword(String keyword) {
    return withParam("keyword", keyword);
  }

  public SearchAttractionsOperation attractionId(String attractionId) {
    return withParam("attractionId", attractionId);
  }

  public SearchAttractionsOperation attractionId(String... attractionIds) {
    return withCommaSeparatedParam("attractionId", attractionIds);
  }

  public SearchAttractionsOperation sort(String sort) {
    return withParam("sort", sort);
  }

  @Override
  protected SearchAttractionsOperation getThis() {
    return this;
  }
} @ToString
@EqualsAndHashCode(callSuper = true)
public class SearchEventsOperation extends PagedOperation<SearchEventsOperation> {

  private static final List<String> UNITS = Arrays.asList("miles", "km");

  public SearchEventsOperation keyword(String keyword) {
    return withParam("keyword", keyword);
  }

  public SearchEventsOperation attractionId(String attractionId) {
    return withParam("attractionId", attractionId);
  }

  public SearchEventsOperation attractionId(String... attractionIds) {
    return withCommaSeparatedParam("attractionId", attractionIds);
  }

  public SearchEventsOperation venueId(String venueId) {
    return withParam("venueId", venueId);
  }

  public SearchEventsOperation venueId(String... venueIds) {
    return withCommaSeparatedParam("venueId", venueIds);
  }

  public SearchEventsOperation promoterId(String promoterId) {
    return withParam("promoterId", promoterId);
  }

  public SearchEventsOperation promoterId(String... promoterIds) {
    return withCommaSeparatedParam("promoterId", promoterIds);
  }

  public SearchEventsOperation postalCode(String postalCode) {
    return withParam("postalCode", postalCode);
  }

  public SearchEventsOperation latlong(String latitude, String longitude) {
    return withParam("latlong", String.format("%s,%s", latitude, longitude));
  }

  public SearchEventsOperation radius(Integer radius) {
    return withParam("radius", radius);
  }

  public SearchEventsOperation unit(String unit) {
    Preconditions.checkArgument(UNITS.contains(unit),
            String.format("Invalid unit, supported units: %s", UNITS.toString()));
    return withParam("unit", unit);
  }

  public SearchEventsOperation marketId(String marketId) {
    return withParam("marketId", marketId);
  }

  public SearchEventsOperation marketIds(String... marketIds) {
    return withCommaSeparatedParam("marketId", marketIds);
  }

  public SearchEventsOperation endDateTime(String endDateTime) {
    return withParam("endDateTime", endDateTime);
  }

  public SearchEventsOperation startDateTime(String startDateTime) {
    return withParam("startDateTime", startDateTime);
  }

  public SearchEventsOperation city(String city) {
    return withParam("city", city);
  }

  public SearchEventsOperation countryCode(String countryCode) {
    return withParam("countryCode", countryCode);
  }

  public SearchEventsOperation countryCode(String... countryCodes) {
    return withCommaSeparatedParam("countryCode", countryCodes);
  }

  public SearchEventsOperation stateCode(String stateCode) {
    return withParam("stateCode", stateCode);
  }

  public SearchEventsOperation stateCode(String... stateCodes) {
    return withCommaSeparatedParam("stateCode", stateCodes);
  }

  public SearchEventsOperation dmaId(String dmaId) {
    return withParam("dmaId", dmaId);
  }

  public SearchEventsOperation dmaId(String... dmaIds) {
    return withCommaSeparatedParam("dmaIds", dmaIds);
  }

  public SearchEventsOperation includeTBA(String includeTBA) {
    return withParam("includeTBA", includeTBA);
  }

  public SearchEventsOperation includeTBD(String includeTBD) {
    return withParam("includeTBD", includeTBD);
  }

  public SearchEventsOperation sort(String sort) {
    return withParam("sort", sort);
  }

  public SearchEventsOperation onsaleEndDateTime(String onsaleEndDateTime) {
    return withParam("onsaleEndDateTime", onsaleEndDateTime);
  }

  public SearchEventsOperation onsaleStartDateTime(String onsaleStartDateTime) {
    return withParam("onsaleStartDateTime", onsaleStartDateTime);
  }

  @Override
  protected SearchEventsOperation getThis() {
    return this;
  }

} @ToString
@EqualsAndHashCode(callSuper = true)
public class SearchVenuesOperation extends PagedOperation<SearchVenuesOperation> {

  public SearchVenuesOperation keyword(String keyword) {
    return withParam("keyword", keyword);
  }

  public SearchVenuesOperation venueId(String venueId) {
    return withParam("venueId", venueId);
  }

  public SearchVenuesOperation venueId(String... venueIds) {
    return withCommaSeparatedParam("venueId", venueIds);
  }

  public SearchVenuesOperation sort(String sort) {
    return withParam("sort", sort);
  }

  public SearchVenuesOperation stateCode(String stateCode) {
    return withParam("stateCode", stateCode);
  }

  public SearchVenuesOperation stateCode(String... stateCode) {
    return withCommaSeparatedParam("stateCode", stateCode);
  }

  public SearchVenuesOperation countryCode(String countryCode) {
    return withParam("countryCode", countryCode);
  }

  public SearchVenuesOperation countryCode(String... countryCode) {
    return withCommaSeparatedParam("countryCode", countryCode);
  }

  @Override
  protected SearchVenuesOperation getThis() {
    return this;
  }
} public class PagedResponse<T> extends Response<T> {

  private final JavaType javaType;
  private Page<T> page;

  public PagedResponse(okhttp3.Response httpResponse, ObjectMapper mapper, Class<T> type) {
    super(httpResponse, mapper, type);
    this.javaType = mapper.getTypeFactory().constructParametricType(Page.class, type);
  }

  protected void readContent() {
    try {
      this.page = mapper.readValue(httpResponse.body().string(), javaType);
    } catch (IOException ioe) {
      throw new RuntimeException(ioe);
    }
    this.content = page.getEmbedded();
  }

  public T getContent() {
    if (content == null) {
      readContent();
    }
    return content;
  }

  public Link getNextPageLink() {
    if (page == null) {
      readContent();
    }
    return page.getLinks().getNext();
  }

  public Link getPreviousPageLink() {
    if (page == null) {
      readContent();
    }
    return page.getLinks().getPrevious();
  }

  public PageInfo getPageInfo() {
    if (page == null) {
      readContent();
    }
    return page.getInfo();
  }

} @ToString(callSuper = true)
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(value = {"type", "_links"})
public class Attraction extends ResourceSupport {

  private String id;
  private String url;
  private Image image;
  private String name;
  private String description;
  private String locale;
  private Boolean test;
  private List<Classification> classifications;
  private List<Image> images;

} @ToString
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Attractions {

  private List<Attraction> attractions;

} @ToString
@EqualsAndHashCode
public class BaseModel {

  private Map<String, Object> otherProperties = new HashMap<String, Object>();
  
  @JsonAnyGetter
  public Map<String,Object> getOtherProperties() {
      return otherProperties;
  }

  @JsonAnySetter
  public void setOtherProperties(String name, Object value) {
    otherProperties.put(name, value);
  }
} @ToString(callSuper = true)
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(value = {"type", "_links"})
public class Event extends ResourceSupport {

  private String id;
  private String name;
  private String description;
  private String locale;
  private String url;
  private Promoter promoter;
  private List<Image> images;
  private List<Classification> classifications;
  private Date dates;
  private Boolean test;
  private Sale sales;
  private String groupId;
  private String info;
  private String pleaseNote;
  private Place place;
  private Set<PriceRange> priceRanges;
  private Source source;

  public List<Venue> getVenues() {
    return embedded != null ? embedded.getVenues() : null;
  }

  public List<Attraction> getAttractions() {
    return embedded != null ? embedded.getAttractions() : null;
  }

  public List<Category> getCategories() {
    return embedded != null ? embedded.getCategories() : null;
  }

  @ToString(callSuper = true)
  @Getter
  @Setter
  @EqualsAndHashCode(callSuper = true)
  @NoArgsConstructor
  @AllArgsConstructor
  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  public static class PriceRange extends BaseModel {

    private String currency;

    private Double min;

    private Double max;

    private String type;

  }
  
} @ToString
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Events {

  private List<Event> events;

} @ToString(callSuper = true)
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(value = {"type", "_links"})
public class Venue extends ResourceSupport {

  private String id;
  private String name;
  private String locale;
  private String url;
  private List<Market> markets;
  private List<DMA> dmas;
  private Country country;
  private State state;
  private City city;
  private Location location;
  private String postalCode;
  private Address address;
  private String timezone;
  private Boolean test;
  private Source source;
  private String accessibleSeatingDetail;
  private String parkingDetail;
  private BoxOfficeInfo boxOfficeInfo;
  private GeneralInfo generalInfo;
  private Social social;
  private Map<String, Extension> extensions = new HashMap<>();
  private Set<Relationship> relationships = new HashSet<>();
  private List<Image> images;

  @ToString(callSuper = true)
  @Getter
  @Setter
  @EqualsAndHashCode(callSuper = true)
  @NoArgsConstructor
  @AllArgsConstructor
  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  public static class Location extends BaseModel {

    private String latitude;

    private String longitude;

  }

  @ToString(callSuper = true)
  @Getter
  @Setter
  @EqualsAndHashCode(callSuper = true)
  @NoArgsConstructor
  @AllArgsConstructor
  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  public static class Country extends BaseModel {

    private String name;
    private String countryCode;

  }

  @ToString(callSuper = true)
  @Getter
  @Setter
  @EqualsAndHashCode(callSuper = true)
  @NoArgsConstructor
  @AllArgsConstructor
  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  public static class State extends BaseModel {

    private String name;
    private String stateCode;

  }

  @ToString(callSuper = true)
  @Getter
  @Setter
  @EqualsAndHashCode(callSuper = true)
  @NoArgsConstructor
  @AllArgsConstructor
  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  public static class City extends BaseModel {

    private String name;

  }

  @ToString(callSuper = true)
  @Getter
  @Setter
  @EqualsAndHashCode(callSuper = true)
  @NoArgsConstructor
  @AllArgsConstructor
  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  public static class Address extends BaseModel {

    private String line1;

    private String line2;

  }

  @ToString(callSuper = true)
  @Getter
  @Setter
  @EqualsAndHashCode(callSuper = true)
  @NoArgsConstructor
  @AllArgsConstructor
  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  public static class BoxOfficeInfo extends BaseModel {

    private String acceptedPaymentDetail;

    private String phoneNumberDetail;

    private String willCallDetail;

    private String openHoursDetail;
    
  }

  @ToString(callSuper = true)
  @Getter
  @Setter
  @EqualsAndHashCode(callSuper = true)
  @NoArgsConstructor
  @AllArgsConstructor
  @JsonInclude(JsonInclude.Include.NON_EMPTY)
  public static class GeneralInfo extends BaseModel {

    private String childRule;

    private String generalRule;

    private String willCallDetail;

  }

} @ToString
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Venues {

  private List<Venue> venues;

}
import java.lang.reflect.Field;
import java.util.Locale;
import java.util.Map;
import okhttp3.HttpUrl;
import org.junit.Test;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;
import org.springframework.util.ReflectionUtils.FieldFilter;
import com.ticketmaster.api.discovery.operation.SearchAttractionsOperation;
import com.ticketmaster.api.discovery.operation.SearchEventsOperation;
import com.ticketmaster.api.discovery.operation.SearchVenuesOperation;
import com.ticketmaster.api.discovery.response.PagedResponse;
import com.ticketmaster.discovery.model.Attraction;
import com.ticketmaster.discovery.model.Attractions;
import com.ticketmaster.discovery.model.BaseModel;
import com.ticketmaster.discovery.model.Event;
import com.ticketmaster.discovery.model.Events;
import com.ticketmaster.discovery.model.Venue;
import com.ticketmaster.discovery.model.Venues;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
package com.ticketmaster.api.discovery;






public class DiscoveryApiITest {

  /**
   * Get the API key from the system properties or in the environment variables
   **/
  private static String apikey = System.getProperty("tm-api-key", System.getenv("TM_API_KEY"));
  private DiscoveryApi api = new DiscoveryApi(apikey);

  @Test
  public void whenCallingSearchEvents_ensureAllFieldsAreInTheModel() throws Exception {
    for (int i = 0; i < 10; i++) {
      PagedResponse<Events> response =