/* 
 * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
 */

package dev.plexapi.sdk.models.operations;


import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import dev.plexapi.sdk.utils.Utils;
import java.lang.Boolean;
import java.lang.Double;
import java.lang.Integer;
import java.lang.Override;
import java.lang.String;
import java.lang.SuppressWarnings;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import java.util.Optional;


public class Metadata {

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("art")
    private Optional<String> art;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("guid")
    private Optional<String> guid;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("key")
    private Optional<String> key;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("ratingKey")
    private Optional<String> ratingKey;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("studio")
    private Optional<String> studio;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("tagline")
    private Optional<String> tagline;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("type")
    private Optional<String> type;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("thumb")
    private Optional<String> thumb;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("addedAt")
    private Optional<Integer> addedAt;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("duration")
    private Optional<Integer> duration;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("publicPagesURL")
    private Optional<String> publicPagesURL;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("slug")
    private Optional<String> slug;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("userState")
    private Optional<Boolean> userState;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("title")
    private Optional<String> title;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("contentRating")
    private Optional<String> contentRating;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("originallyAvailableAt")
    private Optional<LocalDate> originallyAvailableAt;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("year")
    private Optional<Integer> year;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("Image")
    private Optional<? extends List<Image>> image;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("banner")
    private Optional<String> banner;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("rating")
    private Optional<Double> rating;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("expiresAt")
    private Optional<Integer> expiresAt;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("originalTitle")
    private Optional<String> originalTitle;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("audienceRating")
    private Optional<Double> audienceRating;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("audienceRatingImage")
    private Optional<String> audienceRatingImage;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("ratingImage")
    private Optional<String> ratingImage;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("imdbRatingCount")
    private Optional<Integer> imdbRatingCount;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("subtype")
    private Optional<String> subtype;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("theme")
    private Optional<String> theme;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("leafCount")
    private Optional<Integer> leafCount;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("childCount")
    private Optional<Integer> childCount;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("isContinuingSeries")
    private Optional<Boolean> isContinuingSeries;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("skipChildren")
    private Optional<Boolean> skipChildren;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("availabilityId")
    private Optional<String> availabilityId;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("streamingMediaId")
    private Optional<String> streamingMediaId;

    @JsonInclude(Include.NON_ABSENT)
    @JsonProperty("playableKey")
    private Optional<String> playableKey;

    @JsonCreator
    public Metadata(
            @JsonProperty("art") Optional<String> art,
            @JsonProperty("guid") Optional<String> guid,
            @JsonProperty("key") Optional<String> key,
            @JsonProperty("ratingKey") Optional<String> ratingKey,
            @JsonProperty("studio") Optional<String> studio,
            @JsonProperty("tagline") Optional<String> tagline,
            @JsonProperty("type") Optional<String> type,
            @JsonProperty("thumb") Optional<String> thumb,
            @JsonProperty("addedAt") Optional<Integer> addedAt,
            @JsonProperty("duration") Optional<Integer> duration,
            @JsonProperty("publicPagesURL") Optional<String> publicPagesURL,
            @JsonProperty("slug") Optional<String> slug,
            @JsonProperty("userState") Optional<Boolean> userState,
            @JsonProperty("title") Optional<String> title,
            @JsonProperty("contentRating") Optional<String> contentRating,
            @JsonProperty("originallyAvailableAt") Optional<LocalDate> originallyAvailableAt,
            @JsonProperty("year") Optional<Integer> year,
            @JsonProperty("Image") Optional<? extends List<Image>> image,
            @JsonProperty("banner") Optional<String> banner,
            @JsonProperty("rating") Optional<Double> rating,
            @JsonProperty("expiresAt") Optional<Integer> expiresAt,
            @JsonProperty("originalTitle") Optional<String> originalTitle,
            @JsonProperty("audienceRating") Optional<Double> audienceRating,
            @JsonProperty("audienceRatingImage") Optional<String> audienceRatingImage,
            @JsonProperty("ratingImage") Optional<String> ratingImage,
            @JsonProperty("imdbRatingCount") Optional<Integer> imdbRatingCount,
            @JsonProperty("subtype") Optional<String> subtype,
            @JsonProperty("theme") Optional<String> theme,
            @JsonProperty("leafCount") Optional<Integer> leafCount,
            @JsonProperty("childCount") Optional<Integer> childCount,
            @JsonProperty("isContinuingSeries") Optional<Boolean> isContinuingSeries,
            @JsonProperty("skipChildren") Optional<Boolean> skipChildren,
            @JsonProperty("availabilityId") Optional<String> availabilityId,
            @JsonProperty("streamingMediaId") Optional<String> streamingMediaId,
            @JsonProperty("playableKey") Optional<String> playableKey) {
        Utils.checkNotNull(art, "art");
        Utils.checkNotNull(guid, "guid");
        Utils.checkNotNull(key, "key");
        Utils.checkNotNull(ratingKey, "ratingKey");
        Utils.checkNotNull(studio, "studio");
        Utils.checkNotNull(tagline, "tagline");
        Utils.checkNotNull(type, "type");
        Utils.checkNotNull(thumb, "thumb");
        Utils.checkNotNull(addedAt, "addedAt");
        Utils.checkNotNull(duration, "duration");
        Utils.checkNotNull(publicPagesURL, "publicPagesURL");
        Utils.checkNotNull(slug, "slug");
        Utils.checkNotNull(userState, "userState");
        Utils.checkNotNull(title, "title");
        Utils.checkNotNull(contentRating, "contentRating");
        Utils.checkNotNull(originallyAvailableAt, "originallyAvailableAt");
        Utils.checkNotNull(year, "year");
        Utils.checkNotNull(image, "image");
        Utils.checkNotNull(banner, "banner");
        Utils.checkNotNull(rating, "rating");
        Utils.checkNotNull(expiresAt, "expiresAt");
        Utils.checkNotNull(originalTitle, "originalTitle");
        Utils.checkNotNull(audienceRating, "audienceRating");
        Utils.checkNotNull(audienceRatingImage, "audienceRatingImage");
        Utils.checkNotNull(ratingImage, "ratingImage");
        Utils.checkNotNull(imdbRatingCount, "imdbRatingCount");
        Utils.checkNotNull(subtype, "subtype");
        Utils.checkNotNull(theme, "theme");
        Utils.checkNotNull(leafCount, "leafCount");
        Utils.checkNotNull(childCount, "childCount");
        Utils.checkNotNull(isContinuingSeries, "isContinuingSeries");
        Utils.checkNotNull(skipChildren, "skipChildren");
        Utils.checkNotNull(availabilityId, "availabilityId");
        Utils.checkNotNull(streamingMediaId, "streamingMediaId");
        Utils.checkNotNull(playableKey, "playableKey");
        this.art = art;
        this.guid = guid;
        this.key = key;
        this.ratingKey = ratingKey;
        this.studio = studio;
        this.tagline = tagline;
        this.type = type;
        this.thumb = thumb;
        this.addedAt = addedAt;
        this.duration = duration;
        this.publicPagesURL = publicPagesURL;
        this.slug = slug;
        this.userState = userState;
        this.title = title;
        this.contentRating = contentRating;
        this.originallyAvailableAt = originallyAvailableAt;
        this.year = year;
        this.image = image;
        this.banner = banner;
        this.rating = rating;
        this.expiresAt = expiresAt;
        this.originalTitle = originalTitle;
        this.audienceRating = audienceRating;
        this.audienceRatingImage = audienceRatingImage;
        this.ratingImage = ratingImage;
        this.imdbRatingCount = imdbRatingCount;
        this.subtype = subtype;
        this.theme = theme;
        this.leafCount = leafCount;
        this.childCount = childCount;
        this.isContinuingSeries = isContinuingSeries;
        this.skipChildren = skipChildren;
        this.availabilityId = availabilityId;
        this.streamingMediaId = streamingMediaId;
        this.playableKey = playableKey;
    }
    
    public Metadata() {
        this(Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty());
    }

    @JsonIgnore
    public Optional<String> art() {
        return art;
    }

    @JsonIgnore
    public Optional<String> guid() {
        return guid;
    }

    @JsonIgnore
    public Optional<String> key() {
        return key;
    }

    @JsonIgnore
    public Optional<String> ratingKey() {
        return ratingKey;
    }

    @JsonIgnore
    public Optional<String> studio() {
        return studio;
    }

    @JsonIgnore
    public Optional<String> tagline() {
        return tagline;
    }

    @JsonIgnore
    public Optional<String> type() {
        return type;
    }

    @JsonIgnore
    public Optional<String> thumb() {
        return thumb;
    }

    @JsonIgnore
    public Optional<Integer> addedAt() {
        return addedAt;
    }

    @JsonIgnore
    public Optional<Integer> duration() {
        return duration;
    }

    @JsonIgnore
    public Optional<String> publicPagesURL() {
        return publicPagesURL;
    }

    @JsonIgnore
    public Optional<String> slug() {
        return slug;
    }

    @JsonIgnore
    public Optional<Boolean> userState() {
        return userState;
    }

    @JsonIgnore
    public Optional<String> title() {
        return title;
    }

    @JsonIgnore
    public Optional<String> contentRating() {
        return contentRating;
    }

    @JsonIgnore
    public Optional<LocalDate> originallyAvailableAt() {
        return originallyAvailableAt;
    }

    @JsonIgnore
    public Optional<Integer> year() {
        return year;
    }

    @SuppressWarnings("unchecked")
    @JsonIgnore
    public Optional<List<Image>> image() {
        return (Optional<List<Image>>) image;
    }

    @JsonIgnore
    public Optional<String> banner() {
        return banner;
    }

    @JsonIgnore
    public Optional<Double> rating() {
        return rating;
    }

    @JsonIgnore
    public Optional<Integer> expiresAt() {
        return expiresAt;
    }

    @JsonIgnore
    public Optional<String> originalTitle() {
        return originalTitle;
    }

    @JsonIgnore
    public Optional<Double> audienceRating() {
        return audienceRating;
    }

    @JsonIgnore
    public Optional<String> audienceRatingImage() {
        return audienceRatingImage;
    }

    @JsonIgnore
    public Optional<String> ratingImage() {
        return ratingImage;
    }

    @JsonIgnore
    public Optional<Integer> imdbRatingCount() {
        return imdbRatingCount;
    }

    @JsonIgnore
    public Optional<String> subtype() {
        return subtype;
    }

    @JsonIgnore
    public Optional<String> theme() {
        return theme;
    }

    @JsonIgnore
    public Optional<Integer> leafCount() {
        return leafCount;
    }

    @JsonIgnore
    public Optional<Integer> childCount() {
        return childCount;
    }

    @JsonIgnore
    public Optional<Boolean> isContinuingSeries() {
        return isContinuingSeries;
    }

    @JsonIgnore
    public Optional<Boolean> skipChildren() {
        return skipChildren;
    }

    @JsonIgnore
    public Optional<String> availabilityId() {
        return availabilityId;
    }

    @JsonIgnore
    public Optional<String> streamingMediaId() {
        return streamingMediaId;
    }

    @JsonIgnore
    public Optional<String> playableKey() {
        return playableKey;
    }

    public final static Builder builder() {
        return new Builder();
    }

    public Metadata withArt(String art) {
        Utils.checkNotNull(art, "art");
        this.art = Optional.ofNullable(art);
        return this;
    }

    public Metadata withArt(Optional<String> art) {
        Utils.checkNotNull(art, "art");
        this.art = art;
        return this;
    }

    public Metadata withGuid(String guid) {
        Utils.checkNotNull(guid, "guid");
        this.guid = Optional.ofNullable(guid);
        return this;
    }

    public Metadata withGuid(Optional<String> guid) {
        Utils.checkNotNull(guid, "guid");
        this.guid = guid;
        return this;
    }

    public Metadata withKey(String key) {
        Utils.checkNotNull(key, "key");
        this.key = Optional.ofNullable(key);
        return this;
    }

    public Metadata withKey(Optional<String> key) {
        Utils.checkNotNull(key, "key");
        this.key = key;
        return this;
    }

    public Metadata withRatingKey(String ratingKey) {
        Utils.checkNotNull(ratingKey, "ratingKey");
        this.ratingKey = Optional.ofNullable(ratingKey);
        return this;
    }

    public Metadata withRatingKey(Optional<String> ratingKey) {
        Utils.checkNotNull(ratingKey, "ratingKey");
        this.ratingKey = ratingKey;
        return this;
    }

    public Metadata withStudio(String studio) {
        Utils.checkNotNull(studio, "studio");
        this.studio = Optional.ofNullable(studio);
        return this;
    }

    public Metadata withStudio(Optional<String> studio) {
        Utils.checkNotNull(studio, "studio");
        this.studio = studio;
        return this;
    }

    public Metadata withTagline(String tagline) {
        Utils.checkNotNull(tagline, "tagline");
        this.tagline = Optional.ofNullable(tagline);
        return this;
    }

    public Metadata withTagline(Optional<String> tagline) {
        Utils.checkNotNull(tagline, "tagline");
        this.tagline = tagline;
        return this;
    }

    public Metadata withType(String type) {
        Utils.checkNotNull(type, "type");
        this.type = Optional.ofNullable(type);
        return this;
    }

    public Metadata withType(Optional<String> type) {
        Utils.checkNotNull(type, "type");
        this.type = type;
        return this;
    }

    public Metadata withThumb(String thumb) {
        Utils.checkNotNull(thumb, "thumb");
        this.thumb = Optional.ofNullable(thumb);
        return this;
    }

    public Metadata withThumb(Optional<String> thumb) {
        Utils.checkNotNull(thumb, "thumb");
        this.thumb = thumb;
        return this;
    }

    public Metadata withAddedAt(int addedAt) {
        Utils.checkNotNull(addedAt, "addedAt");
        this.addedAt = Optional.ofNullable(addedAt);
        return this;
    }

    public Metadata withAddedAt(Optional<Integer> addedAt) {
        Utils.checkNotNull(addedAt, "addedAt");
        this.addedAt = addedAt;
        return this;
    }

    public Metadata withDuration(int duration) {
        Utils.checkNotNull(duration, "duration");
        this.duration = Optional.ofNullable(duration);
        return this;
    }

    public Metadata withDuration(Optional<Integer> duration) {
        Utils.checkNotNull(duration, "duration");
        this.duration = duration;
        return this;
    }

    public Metadata withPublicPagesURL(String publicPagesURL) {
        Utils.checkNotNull(publicPagesURL, "publicPagesURL");
        this.publicPagesURL = Optional.ofNullable(publicPagesURL);
        return this;
    }

    public Metadata withPublicPagesURL(Optional<String> publicPagesURL) {
        Utils.checkNotNull(publicPagesURL, "publicPagesURL");
        this.publicPagesURL = publicPagesURL;
        return this;
    }

    public Metadata withSlug(String slug) {
        Utils.checkNotNull(slug, "slug");
        this.slug = Optional.ofNullable(slug);
        return this;
    }

    public Metadata withSlug(Optional<String> slug) {
        Utils.checkNotNull(slug, "slug");
        this.slug = slug;
        return this;
    }

    public Metadata withUserState(boolean userState) {
        Utils.checkNotNull(userState, "userState");
        this.userState = Optional.ofNullable(userState);
        return this;
    }

    public Metadata withUserState(Optional<Boolean> userState) {
        Utils.checkNotNull(userState, "userState");
        this.userState = userState;
        return this;
    }

    public Metadata withTitle(String title) {
        Utils.checkNotNull(title, "title");
        this.title = Optional.ofNullable(title);
        return this;
    }

    public Metadata withTitle(Optional<String> title) {
        Utils.checkNotNull(title, "title");
        this.title = title;
        return this;
    }

    public Metadata withContentRating(String contentRating) {
        Utils.checkNotNull(contentRating, "contentRating");
        this.contentRating = Optional.ofNullable(contentRating);
        return this;
    }

    public Metadata withContentRating(Optional<String> contentRating) {
        Utils.checkNotNull(contentRating, "contentRating");
        this.contentRating = contentRating;
        return this;
    }

    public Metadata withOriginallyAvailableAt(LocalDate originallyAvailableAt) {
        Utils.checkNotNull(originallyAvailableAt, "originallyAvailableAt");
        this.originallyAvailableAt = Optional.ofNullable(originallyAvailableAt);
        return this;
    }

    public Metadata withOriginallyAvailableAt(Optional<LocalDate> originallyAvailableAt) {
        Utils.checkNotNull(originallyAvailableAt, "originallyAvailableAt");
        this.originallyAvailableAt = originallyAvailableAt;
        return this;
    }

    public Metadata withYear(int year) {
        Utils.checkNotNull(year, "year");
        this.year = Optional.ofNullable(year);
        return this;
    }

    public Metadata withYear(Optional<Integer> year) {
        Utils.checkNotNull(year, "year");
        this.year = year;
        return this;
    }

    public Metadata withImage(List<Image> image) {
        Utils.checkNotNull(image, "image");
        this.image = Optional.ofNullable(image);
        return this;
    }

    public Metadata withImage(Optional<? extends List<Image>> image) {
        Utils.checkNotNull(image, "image");
        this.image = image;
        return this;
    }

    public Metadata withBanner(String banner) {
        Utils.checkNotNull(banner, "banner");
        this.banner = Optional.ofNullable(banner);
        return this;
    }

    public Metadata withBanner(Optional<String> banner) {
        Utils.checkNotNull(banner, "banner");
        this.banner = banner;
        return this;
    }

    public Metadata withRating(double rating) {
        Utils.checkNotNull(rating, "rating");
        this.rating = Optional.ofNullable(rating);
        return this;
    }

    public Metadata withRating(Optional<Double> rating) {
        Utils.checkNotNull(rating, "rating");
        this.rating = rating;
        return this;
    }

    public Metadata withExpiresAt(int expiresAt) {
        Utils.checkNotNull(expiresAt, "expiresAt");
        this.expiresAt = Optional.ofNullable(expiresAt);
        return this;
    }

    public Metadata withExpiresAt(Optional<Integer> expiresAt) {
        Utils.checkNotNull(expiresAt, "expiresAt");
        this.expiresAt = expiresAt;
        return this;
    }

    public Metadata withOriginalTitle(String originalTitle) {
        Utils.checkNotNull(originalTitle, "originalTitle");
        this.originalTitle = Optional.ofNullable(originalTitle);
        return this;
    }

    public Metadata withOriginalTitle(Optional<String> originalTitle) {
        Utils.checkNotNull(originalTitle, "originalTitle");
        this.originalTitle = originalTitle;
        return this;
    }

    public Metadata withAudienceRating(double audienceRating) {
        Utils.checkNotNull(audienceRating, "audienceRating");
        this.audienceRating = Optional.ofNullable(audienceRating);
        return this;
    }

    public Metadata withAudienceRating(Optional<Double> audienceRating) {
        Utils.checkNotNull(audienceRating, "audienceRating");
        this.audienceRating = audienceRating;
        return this;
    }

    public Metadata withAudienceRatingImage(String audienceRatingImage) {
        Utils.checkNotNull(audienceRatingImage, "audienceRatingImage");
        this.audienceRatingImage = Optional.ofNullable(audienceRatingImage);
        return this;
    }

    public Metadata withAudienceRatingImage(Optional<String> audienceRatingImage) {
        Utils.checkNotNull(audienceRatingImage, "audienceRatingImage");
        this.audienceRatingImage = audienceRatingImage;
        return this;
    }

    public Metadata withRatingImage(String ratingImage) {
        Utils.checkNotNull(ratingImage, "ratingImage");
        this.ratingImage = Optional.ofNullable(ratingImage);
        return this;
    }

    public Metadata withRatingImage(Optional<String> ratingImage) {
        Utils.checkNotNull(ratingImage, "ratingImage");
        this.ratingImage = ratingImage;
        return this;
    }

    public Metadata withImdbRatingCount(int imdbRatingCount) {
        Utils.checkNotNull(imdbRatingCount, "imdbRatingCount");
        this.imdbRatingCount = Optional.ofNullable(imdbRatingCount);
        return this;
    }

    public Metadata withImdbRatingCount(Optional<Integer> imdbRatingCount) {
        Utils.checkNotNull(imdbRatingCount, "imdbRatingCount");
        this.imdbRatingCount = imdbRatingCount;
        return this;
    }

    public Metadata withSubtype(String subtype) {
        Utils.checkNotNull(subtype, "subtype");
        this.subtype = Optional.ofNullable(subtype);
        return this;
    }

    public Metadata withSubtype(Optional<String> subtype) {
        Utils.checkNotNull(subtype, "subtype");
        this.subtype = subtype;
        return this;
    }

    public Metadata withTheme(String theme) {
        Utils.checkNotNull(theme, "theme");
        this.theme = Optional.ofNullable(theme);
        return this;
    }

    public Metadata withTheme(Optional<String> theme) {
        Utils.checkNotNull(theme, "theme");
        this.theme = theme;
        return this;
    }

    public Metadata withLeafCount(int leafCount) {
        Utils.checkNotNull(leafCount, "leafCount");
        this.leafCount = Optional.ofNullable(leafCount);
        return this;
    }

    public Metadata withLeafCount(Optional<Integer> leafCount) {
        Utils.checkNotNull(leafCount, "leafCount");
        this.leafCount = leafCount;
        return this;
    }

    public Metadata withChildCount(int childCount) {
        Utils.checkNotNull(childCount, "childCount");
        this.childCount = Optional.ofNullable(childCount);
        return this;
    }

    public Metadata withChildCount(Optional<Integer> childCount) {
        Utils.checkNotNull(childCount, "childCount");
        this.childCount = childCount;
        return this;
    }

    public Metadata withIsContinuingSeries(boolean isContinuingSeries) {
        Utils.checkNotNull(isContinuingSeries, "isContinuingSeries");
        this.isContinuingSeries = Optional.ofNullable(isContinuingSeries);
        return this;
    }

    public Metadata withIsContinuingSeries(Optional<Boolean> isContinuingSeries) {
        Utils.checkNotNull(isContinuingSeries, "isContinuingSeries");
        this.isContinuingSeries = isContinuingSeries;
        return this;
    }

    public Metadata withSkipChildren(boolean skipChildren) {
        Utils.checkNotNull(skipChildren, "skipChildren");
        this.skipChildren = Optional.ofNullable(skipChildren);
        return this;
    }

    public Metadata withSkipChildren(Optional<Boolean> skipChildren) {
        Utils.checkNotNull(skipChildren, "skipChildren");
        this.skipChildren = skipChildren;
        return this;
    }

    public Metadata withAvailabilityId(String availabilityId) {
        Utils.checkNotNull(availabilityId, "availabilityId");
        this.availabilityId = Optional.ofNullable(availabilityId);
        return this;
    }

    public Metadata withAvailabilityId(Optional<String> availabilityId) {
        Utils.checkNotNull(availabilityId, "availabilityId");
        this.availabilityId = availabilityId;
        return this;
    }

    public Metadata withStreamingMediaId(String streamingMediaId) {
        Utils.checkNotNull(streamingMediaId, "streamingMediaId");
        this.streamingMediaId = Optional.ofNullable(streamingMediaId);
        return this;
    }

    public Metadata withStreamingMediaId(Optional<String> streamingMediaId) {
        Utils.checkNotNull(streamingMediaId, "streamingMediaId");
        this.streamingMediaId = streamingMediaId;
        return this;
    }

    public Metadata withPlayableKey(String playableKey) {
        Utils.checkNotNull(playableKey, "playableKey");
        this.playableKey = Optional.ofNullable(playableKey);
        return this;
    }

    public Metadata withPlayableKey(Optional<String> playableKey) {
        Utils.checkNotNull(playableKey, "playableKey");
        this.playableKey = playableKey;
        return this;
    }
    
    @Override
    public boolean equals(java.lang.Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Metadata other = (Metadata) o;
        return 
            Objects.deepEquals(this.art, other.art) &&
            Objects.deepEquals(this.guid, other.guid) &&
            Objects.deepEquals(this.key, other.key) &&
            Objects.deepEquals(this.ratingKey, other.ratingKey) &&
            Objects.deepEquals(this.studio, other.studio) &&
            Objects.deepEquals(this.tagline, other.tagline) &&
            Objects.deepEquals(this.type, other.type) &&
            Objects.deepEquals(this.thumb, other.thumb) &&
            Objects.deepEquals(this.addedAt, other.addedAt) &&
            Objects.deepEquals(this.duration, other.duration) &&
            Objects.deepEquals(this.publicPagesURL, other.publicPagesURL) &&
            Objects.deepEquals(this.slug, other.slug) &&
            Objects.deepEquals(this.userState, other.userState) &&
            Objects.deepEquals(this.title, other.title) &&
            Objects.deepEquals(this.contentRating, other.contentRating) &&
            Objects.deepEquals(this.originallyAvailableAt, other.originallyAvailableAt) &&
            Objects.deepEquals(this.year, other.year) &&
            Objects.deepEquals(this.image, other.image) &&
            Objects.deepEquals(this.banner, other.banner) &&
            Objects.deepEquals(this.rating, other.rating) &&
            Objects.deepEquals(this.expiresAt, other.expiresAt) &&
            Objects.deepEquals(this.originalTitle, other.originalTitle) &&
            Objects.deepEquals(this.audienceRating, other.audienceRating) &&
            Objects.deepEquals(this.audienceRatingImage, other.audienceRatingImage) &&
            Objects.deepEquals(this.ratingImage, other.ratingImage) &&
            Objects.deepEquals(this.imdbRatingCount, other.imdbRatingCount) &&
            Objects.deepEquals(this.subtype, other.subtype) &&
            Objects.deepEquals(this.theme, other.theme) &&
            Objects.deepEquals(this.leafCount, other.leafCount) &&
            Objects.deepEquals(this.childCount, other.childCount) &&
            Objects.deepEquals(this.isContinuingSeries, other.isContinuingSeries) &&
            Objects.deepEquals(this.skipChildren, other.skipChildren) &&
            Objects.deepEquals(this.availabilityId, other.availabilityId) &&
            Objects.deepEquals(this.streamingMediaId, other.streamingMediaId) &&
            Objects.deepEquals(this.playableKey, other.playableKey);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(
            art,
            guid,
            key,
            ratingKey,
            studio,
            tagline,
            type,
            thumb,
            addedAt,
            duration,
            publicPagesURL,
            slug,
            userState,
            title,
            contentRating,
            originallyAvailableAt,
            year,
            image,
            banner,
            rating,
            expiresAt,
            originalTitle,
            audienceRating,
            audienceRatingImage,
            ratingImage,
            imdbRatingCount,
            subtype,
            theme,
            leafCount,
            childCount,
            isContinuingSeries,
            skipChildren,
            availabilityId,
            streamingMediaId,
            playableKey);
    }
    
    @Override
    public String toString() {
        return Utils.toString(Metadata.class,
                "art", art,
                "guid", guid,
                "key", key,
                "ratingKey", ratingKey,
                "studio", studio,
                "tagline", tagline,
                "type", type,
                "thumb", thumb,
                "addedAt", addedAt,
                "duration", duration,
                "publicPagesURL", publicPagesURL,
                "slug", slug,
                "userState", userState,
                "title", title,
                "contentRating", contentRating,
                "originallyAvailableAt", originallyAvailableAt,
                "year", year,
                "image", image,
                "banner", banner,
                "rating", rating,
                "expiresAt", expiresAt,
                "originalTitle", originalTitle,
                "audienceRating", audienceRating,
                "audienceRatingImage", audienceRatingImage,
                "ratingImage", ratingImage,
                "imdbRatingCount", imdbRatingCount,
                "subtype", subtype,
                "theme", theme,
                "leafCount", leafCount,
                "childCount", childCount,
                "isContinuingSeries", isContinuingSeries,
                "skipChildren", skipChildren,
                "availabilityId", availabilityId,
                "streamingMediaId", streamingMediaId,
                "playableKey", playableKey);
    }
    
    public final static class Builder {
 
        private Optional<String> art = Optional.empty();
 
        private Optional<String> guid = Optional.empty();
 
        private Optional<String> key = Optional.empty();
 
        private Optional<String> ratingKey = Optional.empty();
 
        private Optional<String> studio = Optional.empty();
 
        private Optional<String> tagline = Optional.empty();
 
        private Optional<String> type = Optional.empty();
 
        private Optional<String> thumb = Optional.empty();
 
        private Optional<Integer> addedAt = Optional.empty();
 
        private Optional<Integer> duration = Optional.empty();
 
        private Optional<String> publicPagesURL = Optional.empty();
 
        private Optional<String> slug = Optional.empty();
 
        private Optional<Boolean> userState = Optional.empty();
 
        private Optional<String> title = Optional.empty();
 
        private Optional<String> contentRating = Optional.empty();
 
        private Optional<LocalDate> originallyAvailableAt = Optional.empty();
 
        private Optional<Integer> year = Optional.empty();
 
        private Optional<? extends List<Image>> image = Optional.empty();
 
        private Optional<String> banner = Optional.empty();
 
        private Optional<Double> rating = Optional.empty();
 
        private Optional<Integer> expiresAt = Optional.empty();
 
        private Optional<String> originalTitle = Optional.empty();
 
        private Optional<Double> audienceRating = Optional.empty();
 
        private Optional<String> audienceRatingImage = Optional.empty();
 
        private Optional<String> ratingImage = Optional.empty();
 
        private Optional<Integer> imdbRatingCount = Optional.empty();
 
        private Optional<String> subtype = Optional.empty();
 
        private Optional<String> theme = Optional.empty();
 
        private Optional<Integer> leafCount = Optional.empty();
 
        private Optional<Integer> childCount = Optional.empty();
 
        private Optional<Boolean> isContinuingSeries = Optional.empty();
 
        private Optional<Boolean> skipChildren = Optional.empty();
 
        private Optional<String> availabilityId = Optional.empty();
 
        private Optional<String> streamingMediaId = Optional.empty();
 
        private Optional<String> playableKey = Optional.empty();  
        
        private Builder() {
          // force use of static builder() method
        }

        public Builder art(String art) {
            Utils.checkNotNull(art, "art");
            this.art = Optional.ofNullable(art);
            return this;
        }

        public Builder art(Optional<String> art) {
            Utils.checkNotNull(art, "art");
            this.art = art;
            return this;
        }

        public Builder guid(String guid) {
            Utils.checkNotNull(guid, "guid");
            this.guid = Optional.ofNullable(guid);
            return this;
        }

        public Builder guid(Optional<String> guid) {
            Utils.checkNotNull(guid, "guid");
            this.guid = guid;
            return this;
        }

        public Builder key(String key) {
            Utils.checkNotNull(key, "key");
            this.key = Optional.ofNullable(key);
            return this;
        }

        public Builder key(Optional<String> key) {
            Utils.checkNotNull(key, "key");
            this.key = key;
            return this;
        }

        public Builder ratingKey(String ratingKey) {
            Utils.checkNotNull(ratingKey, "ratingKey");
            this.ratingKey = Optional.ofNullable(ratingKey);
            return this;
        }

        public Builder ratingKey(Optional<String> ratingKey) {
            Utils.checkNotNull(ratingKey, "ratingKey");
            this.ratingKey = ratingKey;
            return this;
        }

        public Builder studio(String studio) {
            Utils.checkNotNull(studio, "studio");
            this.studio = Optional.ofNullable(studio);
            return this;
        }

        public Builder studio(Optional<String> studio) {
            Utils.checkNotNull(studio, "studio");
            this.studio = studio;
            return this;
        }

        public Builder tagline(String tagline) {
            Utils.checkNotNull(tagline, "tagline");
            this.tagline = Optional.ofNullable(tagline);
            return this;
        }

        public Builder tagline(Optional<String> tagline) {
            Utils.checkNotNull(tagline, "tagline");
            this.tagline = tagline;
            return this;
        }

        public Builder type(String type) {
            Utils.checkNotNull(type, "type");
            this.type = Optional.ofNullable(type);
            return this;
        }

        public Builder type(Optional<String> type) {
            Utils.checkNotNull(type, "type");
            this.type = type;
            return this;
        }

        public Builder thumb(String thumb) {
            Utils.checkNotNull(thumb, "thumb");
            this.thumb = Optional.ofNullable(thumb);
            return this;
        }

        public Builder thumb(Optional<String> thumb) {
            Utils.checkNotNull(thumb, "thumb");
            this.thumb = thumb;
            return this;
        }

        public Builder addedAt(int addedAt) {
            Utils.checkNotNull(addedAt, "addedAt");
            this.addedAt = Optional.ofNullable(addedAt);
            return this;
        }

        public Builder addedAt(Optional<Integer> addedAt) {
            Utils.checkNotNull(addedAt, "addedAt");
            this.addedAt = addedAt;
            return this;
        }

        public Builder duration(int duration) {
            Utils.checkNotNull(duration, "duration");
            this.duration = Optional.ofNullable(duration);
            return this;
        }

        public Builder duration(Optional<Integer> duration) {
            Utils.checkNotNull(duration, "duration");
            this.duration = duration;
            return this;
        }

        public Builder publicPagesURL(String publicPagesURL) {
            Utils.checkNotNull(publicPagesURL, "publicPagesURL");
            this.publicPagesURL = Optional.ofNullable(publicPagesURL);
            return this;
        }

        public Builder publicPagesURL(Optional<String> publicPagesURL) {
            Utils.checkNotNull(publicPagesURL, "publicPagesURL");
            this.publicPagesURL = publicPagesURL;
            return this;
        }

        public Builder slug(String slug) {
            Utils.checkNotNull(slug, "slug");
            this.slug = Optional.ofNullable(slug);
            return this;
        }

        public Builder slug(Optional<String> slug) {
            Utils.checkNotNull(slug, "slug");
            this.slug = slug;
            return this;
        }

        public Builder userState(boolean userState) {
            Utils.checkNotNull(userState, "userState");
            this.userState = Optional.ofNullable(userState);
            return this;
        }

        public Builder userState(Optional<Boolean> userState) {
            Utils.checkNotNull(userState, "userState");
            this.userState = userState;
            return this;
        }

        public Builder title(String title) {
            Utils.checkNotNull(title, "title");
            this.title = Optional.ofNullable(title);
            return this;
        }

        public Builder title(Optional<String> title) {
            Utils.checkNotNull(title, "title");
            this.title = title;
            return this;
        }

        public Builder contentRating(String contentRating) {
            Utils.checkNotNull(contentRating, "contentRating");
            this.contentRating = Optional.ofNullable(contentRating);
            return this;
        }

        public Builder contentRating(Optional<String> contentRating) {
            Utils.checkNotNull(contentRating, "contentRating");
            this.contentRating = contentRating;
            return this;
        }

        public Builder originallyAvailableAt(LocalDate originallyAvailableAt) {
            Utils.checkNotNull(originallyAvailableAt, "originallyAvailableAt");
            this.originallyAvailableAt = Optional.ofNullable(originallyAvailableAt);
            return this;
        }

        public Builder originallyAvailableAt(Optional<LocalDate> originallyAvailableAt) {
            Utils.checkNotNull(originallyAvailableAt, "originallyAvailableAt");
            this.originallyAvailableAt = originallyAvailableAt;
            return this;
        }

        public Builder year(int year) {
            Utils.checkNotNull(year, "year");
            this.year = Optional.ofNullable(year);
            return this;
        }

        public Builder year(Optional<Integer> year) {
            Utils.checkNotNull(year, "year");
            this.year = year;
            return this;
        }

        public Builder image(List<Image> image) {
            Utils.checkNotNull(image, "image");
            this.image = Optional.ofNullable(image);
            return this;
        }

        public Builder image(Optional<? extends List<Image>> image) {
            Utils.checkNotNull(image, "image");
            this.image = image;
            return this;
        }

        public Builder banner(String banner) {
            Utils.checkNotNull(banner, "banner");
            this.banner = Optional.ofNullable(banner);
            return this;
        }

        public Builder banner(Optional<String> banner) {
            Utils.checkNotNull(banner, "banner");
            this.banner = banner;
            return this;
        }

        public Builder rating(double rating) {
            Utils.checkNotNull(rating, "rating");
            this.rating = Optional.ofNullable(rating);
            return this;
        }

        public Builder rating(Optional<Double> rating) {
            Utils.checkNotNull(rating, "rating");
            this.rating = rating;
            return this;
        }

        public Builder expiresAt(int expiresAt) {
            Utils.checkNotNull(expiresAt, "expiresAt");
            this.expiresAt = Optional.ofNullable(expiresAt);
            return this;
        }

        public Builder expiresAt(Optional<Integer> expiresAt) {
            Utils.checkNotNull(expiresAt, "expiresAt");
            this.expiresAt = expiresAt;
            return this;
        }

        public Builder originalTitle(String originalTitle) {
            Utils.checkNotNull(originalTitle, "originalTitle");
            this.originalTitle = Optional.ofNullable(originalTitle);
            return this;
        }

        public Builder originalTitle(Optional<String> originalTitle) {
            Utils.checkNotNull(originalTitle, "originalTitle");
            this.originalTitle = originalTitle;
            return this;
        }

        public Builder audienceRating(double audienceRating) {
            Utils.checkNotNull(audienceRating, "audienceRating");
            this.audienceRating = Optional.ofNullable(audienceRating);
            return this;
        }

        public Builder audienceRating(Optional<Double> audienceRating) {
            Utils.checkNotNull(audienceRating, "audienceRating");
            this.audienceRating = audienceRating;
            return this;
        }

        public Builder audienceRatingImage(String audienceRatingImage) {
            Utils.checkNotNull(audienceRatingImage, "audienceRatingImage");
            this.audienceRatingImage = Optional.ofNullable(audienceRatingImage);
            return this;
        }

        public Builder audienceRatingImage(Optional<String> audienceRatingImage) {
            Utils.checkNotNull(audienceRatingImage, "audienceRatingImage");
            this.audienceRatingImage = audienceRatingImage;
            return this;
        }

        public Builder ratingImage(String ratingImage) {
            Utils.checkNotNull(ratingImage, "ratingImage");
            this.ratingImage = Optional.ofNullable(ratingImage);
            return this;
        }

        public Builder ratingImage(Optional<String> ratingImage) {
            Utils.checkNotNull(ratingImage, "ratingImage");
            this.ratingImage = ratingImage;
            return this;
        }

        public Builder imdbRatingCount(int imdbRatingCount) {
            Utils.checkNotNull(imdbRatingCount, "imdbRatingCount");
            this.imdbRatingCount = Optional.ofNullable(imdbRatingCount);
            return this;
        }

        public Builder imdbRatingCount(Optional<Integer> imdbRatingCount) {
            Utils.checkNotNull(imdbRatingCount, "imdbRatingCount");
            this.imdbRatingCount = imdbRatingCount;
            return this;
        }

        public Builder subtype(String subtype) {
            Utils.checkNotNull(subtype, "subtype");
            this.subtype = Optional.ofNullable(subtype);
            return this;
        }

        public Builder subtype(Optional<String> subtype) {
            Utils.checkNotNull(subtype, "subtype");
            this.subtype = subtype;
            return this;
        }

        public Builder theme(String theme) {
            Utils.checkNotNull(theme, "theme");
            this.theme = Optional.ofNullable(theme);
            return this;
        }

        public Builder theme(Optional<String> theme) {
            Utils.checkNotNull(theme, "theme");
            this.theme = theme;
            return this;
        }

        public Builder leafCount(int leafCount) {
            Utils.checkNotNull(leafCount, "leafCount");
            this.leafCount = Optional.ofNullable(leafCount);
            return this;
        }

        public Builder leafCount(Optional<Integer> leafCount) {
            Utils.checkNotNull(leafCount, "leafCount");
            this.leafCount = leafCount;
            return this;
        }

        public Builder childCount(int childCount) {
            Utils.checkNotNull(childCount, "childCount");
            this.childCount = Optional.ofNullable(childCount);
            return this;
        }

        public Builder childCount(Optional<Integer> childCount) {
            Utils.checkNotNull(childCount, "childCount");
            this.childCount = childCount;
            return this;
        }

        public Builder isContinuingSeries(boolean isContinuingSeries) {
            Utils.checkNotNull(isContinuingSeries, "isContinuingSeries");
            this.isContinuingSeries = Optional.ofNullable(isContinuingSeries);
            return this;
        }

        public Builder isContinuingSeries(Optional<Boolean> isContinuingSeries) {
            Utils.checkNotNull(isContinuingSeries, "isContinuingSeries");
            this.isContinuingSeries = isContinuingSeries;
            return this;
        }

        public Builder skipChildren(boolean skipChildren) {
            Utils.checkNotNull(skipChildren, "skipChildren");
            this.skipChildren = Optional.ofNullable(skipChildren);
            return this;
        }

        public Builder skipChildren(Optional<Boolean> skipChildren) {
            Utils.checkNotNull(skipChildren, "skipChildren");
            this.skipChildren = skipChildren;
            return this;
        }

        public Builder availabilityId(String availabilityId) {
            Utils.checkNotNull(availabilityId, "availabilityId");
            this.availabilityId = Optional.ofNullable(availabilityId);
            return this;
        }

        public Builder availabilityId(Optional<String> availabilityId) {
            Utils.checkNotNull(availabilityId, "availabilityId");
            this.availabilityId = availabilityId;
            return this;
        }

        public Builder streamingMediaId(String streamingMediaId) {
            Utils.checkNotNull(streamingMediaId, "streamingMediaId");
            this.streamingMediaId = Optional.ofNullable(streamingMediaId);
            return this;
        }

        public Builder streamingMediaId(Optional<String> streamingMediaId) {
            Utils.checkNotNull(streamingMediaId, "streamingMediaId");
            this.streamingMediaId = streamingMediaId;
            return this;
        }

        public Builder playableKey(String playableKey) {
            Utils.checkNotNull(playableKey, "playableKey");
            this.playableKey = Optional.ofNullable(playableKey);
            return this;
        }

        public Builder playableKey(Optional<String> playableKey) {
            Utils.checkNotNull(playableKey, "playableKey");
            this.playableKey = playableKey;
            return this;
        }
        
        public Metadata build() {
            return new Metadata(
                art,
                guid,
                key,
                ratingKey,
                studio,
                tagline,
                type,
                thumb,
                addedAt,
                duration,
                publicPagesURL,
                slug,
                userState,
                title,
                contentRating,
                originallyAvailableAt,
                year,
                image,
                banner,
                rating,
                expiresAt,
                originalTitle,
                audienceRating,
                audienceRatingImage,
                ratingImage,
                imdbRatingCount,
                subtype,
                theme,
                leafCount,
                childCount,
                isContinuingSeries,
                skipChildren,
                availabilityId,
                streamingMediaId,
                playableKey);
        }
    }
}

