All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.micronaut.rss.jsonfeed.JsonFeed Maven / Gradle / Ivy

/*
 * Copyright 2017-2020 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.micronaut.rss.jsonfeed;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.annotation.Introspected;
import io.micronaut.rss.language.RssLanguage;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;

/**
 * A JSON Feed is a list that may change over time, and the individual items in the list may change..
 * @see JSON Feed 1.1
 * @author Sergio del Amo, mark1626
 * @since 2.2.0
 */
@Introspected
public class JsonFeed {

    public static final String VERSION_JSON_FEED_1 = "https://jsonfeed.org/version/1";
    public static final String VERSION_JSON_FEED_1_1 = "https://jsonfeed.org/version/1.1";

    public static final String KEY_VERSION = "version";
    public static final String KEY_TITLE = "title";
    public static final String KEY_HOME_PAGE_URL = "home_page_url";
    public static final String KEY_FEED_URL = "feed_url";
    public static final String KEY_DESCRIPTION = "description";
    public static final String KEY_USER_COMMENT = "user_comment";
    public static final String KEY_NEXT_URL = "next_url";
    public static final String KEY_ICON = "icon";
    public static final String KEY_FAVICON = "favicon";
    public static final String KEY_AUTHORS = "authors";
    public static final String KEY_ITEMS = "items";
    public static final String KEY_AUTHOR = "author";
    public static final String KEY_LANGUAGE = "language";
    public static final String KEY_EXPIRED = "expired";
    public static final String KEY_HUBS = "hubs";

    /**
     * The URL of the version of the format the feed uses.
     */
    @NotBlank
    @NonNull
    private String version;

    /**
     * The name of the feed, which will often correspond to the name of the website (blog, for instance), though not necessarily.
     */
    @NotBlank
    @NonNull
    private String title;

    /**
     * he URL of the resource that the feed describes. This resource may or may not actually be a “home” page, but it should be an HTML page. If a feed is published on the public web, this should be considered as required. But it may not make sense in the case of a file created on a desktop computer, when that file is not shared or is shared only privately.
     */
    @Nullable
    @JsonProperty(KEY_HOME_PAGE_URL)
    private String homePageUrl;

    /**
     * The URL of the feed, and serves as the unique identifier for the feed. As with home_page_url, this should be considered required for feeds on the public web.
     */
    @JsonProperty(KEY_FEED_URL)
    @Nullable
    private String feedUrl;

    /**
     * Provides more detail, beyond the title, on what the feed is about. A feed reader may display this text.
     */
    @Nullable
    private String description;

    /**
     * This is a description of the purpose of the feed. This is for the use of people looking at the raw JSON, and should be ignored by feed readers.
     */
    @JsonProperty(KEY_USER_COMMENT)
    @Nullable
    private String userComment;

    /**
     * The URL of a feed that provides the next n items, where n is determined by the publisher.
     * This allows for pagination, but with the expectation that reader software is not required to use it and probably won’t use it very often
     */
    @JsonProperty(KEY_NEXT_URL)
    @Nullable
    private String nextURL;

    /**
     * The URL of an image for the feed suitable to be used in a timeline, much the way an avatar might be used. It should be square and relatively large — such as 512 x 512 pixels — so that it can be scaled-down and so that it can look good on retina displays. It should use transparency where appropriate, since it may be rendered on a non-white background.
     */
    @Nullable
    private String icon;

    /**
     * The URL of an image for the feed suitable to be used in a source list. It should be square and relatively small, but not smaller than 64 x 64 pixels (so that it can look good on retina displays). As with icon, this image should use transparency where appropriate, since it may be rendered on a non-white background.
     */
    @Nullable
    private String favicon;

    @Nullable
    private List<@Valid JsonFeedAuthor> authors;

    @NonNull
    @NotEmpty
    private List<@Valid JsonFeedItem> items;

    @Pattern(regexp = RssLanguage.LANGUAGE_CODE_PATTERN)
    @Nullable
    private String language;

    @Nullable
    private Boolean expired;

    @Nullable
    private List<@Valid JsonHub> hubs;

    /**
     * @return JSON Feed Builder
     */
    @NonNull
    public static Builder builder() {
        return new Builder();
    }

    /**
     * Creates builder with required fields.
     *
     * @param title JSON Feed's title
     * @param items JSON Feed's items
     * @return JSON Feed Builder
     */
    @NonNull
    public static Builder builder(@NonNull String title, @NonNull List items) {
        return new Builder().title(title).version(VERSION_JSON_FEED_1_1).items(items);
    }

    /**
     *
     * @param version JSON Feed version
     * @param title JSON Feed's title
     * @param items JSON Feed's items
     * @return JSON Feed Builder
     */
    @NonNull
    public static Builder builder(@NonNull String version, @NonNull String title, @NonNull List items) {
        return new Builder().title(title).version(version).items(items);
    }

    /**
     * URL of the version of the format the feed uses.
     *
     * @param version of JSON feed
     */
    public void setVersion(@NonNull String version) {
        this.version = version;
    }

    /**
     * Returns the URL of the version of the format the feed uses.
     *
     * @return version of JSON feed
     */
    @NonNull
    public String getVersion() {
        return this.version;
    }

    /**
     * The name of the feed, which will often correspond to the name of the website.
     *
     * @return the name of the feed
     */
    @NonNull
    public String getTitle() {
        return this.title;
    }

    /**
     * The name of the feed, which will often correspond to the name of the website.
     *
     * @param title the name of the feed
     */
    public void setTitle(@NonNull String title) {
        this.title = title;
    }

    /**
     * The URL of the resource that the feed describes. This resource may or may not actually be a
     * “home” page, but it should be an HTML page
     *
     * @return The URL of the resource that the feed describes
     */
    @Nullable
    public String getHomePageUrl() {
        return this.homePageUrl;
    }

    /**
     * The URL of the resource that the feed describes. This resource may or may not actually be a
     * “home” page, but it should be an HTML page
     *
     * @param homePageUrl The URL of the resource that the feed describes
     */
    public void setHomePageUrl(@Nullable String homePageUrl) {
        this.homePageUrl = homePageUrl;
    }

    /**
     * Detail on what the feed is about. A feed reader may display this text.
     *
     * @return detail on what the feed is about
     */
    public String getDescription() {
        return this.description;
    }

    /**
     * Detail on what the feed is about. A feed reader may display this text.
     *
     * @param description detail on what the feed is about
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * The URL of the feed, and serves as the unique identifier for the feed.
     *
     * @return the URL of the feed, and serves as the unique identifier for the feed
     */
    @Nullable
    public String getFeedUrl() {
        return this.feedUrl;
    }

    /**
     * The URL of the feed, and serves as the unique identifier for the feed.
     *
     * @param feedUrl the URL of the feed, and serves as the unique identifier for the feed
     */
    public void setFeedUrl(@Nullable String feedUrl) {
        this.feedUrl = feedUrl;
    }

    /**
     * Description of the purpose of the feed. This is for the use of people looking at the raw
     * JSON, and should be ignored by feed readers
     *
     * @return description of the purpose of the feed.
     */
    @Nullable
    public String getUserComment() {
        return userComment;
    }

    /**
     * Description of the purpose of the feed. This is for the use of people looking at the raw
     * JSON, and should be ignored by feed readers
     *
     * @param userComment description of the purpose of the feed.
     */
    public void setUserComment(@Nullable String userComment) {
        this.userComment = userComment;
    }

    /**
     * The URL of a feed that provides the next n items, where n is determined by the publisher.
     * This allows for pagination, but with the expectation that reader software is not required to
     * use it and probably won’t use it very often
     *
     * @return the URL of a feed that provides the next n items
     */
    @Nullable
    public String getNextURL() {
        return nextURL;
    }

    /**
     * The URL of a feed that provides the next n items, where n is determined by the publisher.
     * This allows for pagination, but with the expectation that reader software is not required to
     * use it and probably won’t use it very often
     *
     * @param nextURL the URL of a feed that provides the next n items
     */
    public void setNextURL(@Nullable String nextURL) {
        this.nextURL = nextURL;
    }

    /**
     * The URL of an image for the feed suitable to be used in a timeline, much the way an avatar
     * might be used. It should be square and relatively large — such as 512 x 512 pixels
     *
     * @return the URL of an image for the feed suitable to be used in a timeline
     */
    @Nullable
    public String getIcon() {
        return icon;
    }

    /**
     * The URL of an image for the feed suitable to be used in a timeline, much the way an avatar
     * might be used. It should be square and relatively large — such as 512 x 512 pixels
     *
     * @param icon the URL of an image for the feed suitable to be used in a timeline
     */
    public void setIcon(@Nullable String icon) {
        this.icon = icon;
    }

    /**
     * The URL of an image for the feed suitable to be used in a source list. It should be square
     * and relatively small, but not smaller than 64 x 64 pixels
     *
     * @return the URL of an image for the feed suitable to be used in a source list
     */
    @Nullable
    public String getFavicon() {
        return favicon;
    }

    /**
     * The URL of an image for the feed suitable to be used in a source list. It should be square
     * and relatively small, but not smaller than 64 x 64 pixels
     *
     * @param favicon the URL of an image for the feed suitable to be used in a source list
     */
    public void setFavicon(@Nullable String favicon) {
        this.favicon = favicon;
    }

    /**
     * Specifies one or more feed authors. The author object has several members
     *
     * @return specifies one or more feed authors
     */
    public List<@Valid JsonFeedAuthor> getAuthors() {
        return authors;
    }

    /**
     * Specifies one or more feed authors. The author object has several members
     *
     * @param authors specifies one or more feed authors
     */
    public void setAuthors(@Nullable List<@Valid JsonFeedAuthor> authors) {
        this.authors = authors;
    }

    /**
     * The primary language for the feed in the format specified in RFC 5646.
     *
     * @return the primary language for the feed
     */
    @Nullable
    public String getLanguage() {
        return language;
    }

    /**
     * The primary language for the feed in the format specified in RFC 5646.
     *
     * @param language the primary language for the feed
     */
    public void setLanguage(@Nullable String language) {
        this.language = language;
    }

    /**
     * Says whether or not the feed is finished — that is, whether or not it will ever update again.
     *
     * @return expired says whether or not the feed is finished
     */
    @Nullable
    public Boolean getExpired() {
        return expired;
    }

    /**
     * Says whether or not the feed is finished — that is, whether or not it will ever update again.
     *
     * @param expired says whether or not the feed is finished
     */
    public void setExpired(@Nullable Boolean expired) {
        this.expired = expired;
    }

    /**
     * Describes endpoints that can be used to subscribe to real-time notifications from the
     * publisher of this feed.
     *
     * @return Describes endpoints that can be used to subscribe to real-time notifications
     */
    @Nullable
    public List<@Valid JsonHub> getHubs() {
        return hubs;
    }

    /**
     * Describes endpoints that can be used to subscribe to real-time notifications from the
     * publisher of this feed.
     *
     * @param hubs Describes endpoints that can be used to subscribe to real-time notifications
     */
    public void setHubs(@Nullable List<@Valid JsonHub> hubs) {
        this.hubs = hubs;
    }

    /**
     *
     * @param hub Endpoint that can be used to subscribe to real-time notifications from the publisher of this feed.
     */
    public void addHub(@NonNull JsonHub hub) {
        if (this.hubs == null) {
            this.hubs = new ArrayList<>();
        }
        this.hubs.add(hub);
    }

    /**
     * The items in the field.
     *
     * @return list of items in the feed
     */
    @NonNull
    public List getItems() {
        return items;
    }

    /**
     * The items in the field.
     *
     * @param items list of items in the feed
     */
    public void setItems(@NonNull List items) {
        this.items = items;
    }

    /**
     *
     * @param author Global JSON Feed's author
     */
    public void addAuthor(@NonNull JsonFeedAuthor author) {
        if (this.authors == null) {
            this.authors = new ArrayList<>();
        }
        this.authors.add(author);
    }

    /**
     *
     * @param item JSON Feed's item
     */
    public void addItem(@NonNull JsonFeedItem item) {
        if (this.items == null) {
            this.items = new ArrayList<>();
        }
        this.items.add(item);
    }

    /**
     *
     * @return Map representation of Object.
     */
    @NonNull
    public Map toMap() {
        Map m = new HashMap<>();
        if (getVersion() != null) {
            m.put(KEY_VERSION, getVersion());
        }
        if (getTitle() != null) {
            m.put(KEY_TITLE, getTitle());
        }
        if (getHomePageUrl() != null) {
            m.put(KEY_HOME_PAGE_URL, getHomePageUrl());
        }
        if (getFeedUrl() != null) {
            m.put(KEY_FEED_URL, getFeedUrl());
        }
        if (getDescription() != null) {
            m.put(KEY_DESCRIPTION, getDescription());
        }
        if (getUserComment() != null) {
            m.put(KEY_USER_COMMENT, getUserComment());
        }
        if (getNextURL() != null) {
            m.put(KEY_NEXT_URL, getNextURL());
        }
        if (getIcon() != null) {
            m.put(KEY_ICON, getIcon());
        }
        if (getFavicon() != null) {
            m.put(KEY_FAVICON, getFavicon());
        }
        if (getAuthors() != null) {
            m.put(KEY_AUTHORS, getAuthors().stream().map(JsonFeedAuthor::toMap).collect(Collectors.toList()));
        }
        if (getItems() != null) {
            m.put(KEY_ITEMS, getItems().stream().map(JsonFeedItem::toMap).collect(Collectors.toList()));
        }
        if (getLanguage() != null) {
            m.put(KEY_LANGUAGE, getLanguage());
        }
        if (getExpired() != null) {
            m.put(KEY_EXPIRED, getExpired());
        }
        if (getHubs() != null) {
            m.put(KEY_HUBS, getHubs().stream().map(JsonHub::toMap).collect(Collectors.toList()));
        }
        return m;
    }

    /**
     * JSON Feed Builder.
     */
    public static final class Builder {

        private final JsonFeed feed = new JsonFeed();

        /**
         * JSON Feed Builder Constructor.
         */
        private Builder() {
        }

        @NonNull
        public JsonFeed build() {
            return this.feed;
        }

        @NonNull
        public Builder version(@NonNull String version) {
            this.feed.setVersion(version);
            return this;
        }

        /**
         * The name of the feed, which will often correspond to the name of the website.
         *
         * @param title the name of the feed
         * @return Builder
         */
        @NonNull
        public Builder title(@NonNull String title) {
            this.feed.setTitle(title);
            return this;
        }

        /**
         * The URL of the resource that the feed describes. This resource may or may not actually be
         * a “home” page, but it should be an HTML page
         *
         * @param homePageUrl The URL of the resource that the feed describes
         * @return Builder
         */
        @NonNull
        public Builder homePageUrl(@NonNull String homePageUrl) {
            this.feed.setHomePageUrl(homePageUrl);
            return this;
        }

        /**
         * The URL of the feed, and serves as the unique identifier for the feed.
         *
         * @param feedUrl the URL of the feed, and serves as the unique identifier for the feed
         * @return Builder
         */
        @NonNull
        public Builder feedUrl(@NonNull String feedUrl) {
            this.feed.setFeedUrl(feedUrl);
            return this;
        }

        /**
         * Detail on what the feed is about. A feed reader may display this text.
         *
         * @param description detail on what the feed is about
         * @return Builder
         */
        @NonNull
        public Builder description(@NonNull String description) {
            this.feed.setDescription(description);
            return this;
        }

        /**
         * Description of the purpose of the feed. This is for the use of people looking at the raw
         * JSON, and should be ignored by feed readers
         *
         * @param userComment description of the purpose of the feed.
         * @return Builder
         */
        @NonNull
        public Builder userComment(@NonNull String userComment) {
            this.feed.setUserComment(userComment);
            return this;
        }

        /**
         * The URL of a feed that provides the next n items, where n is determined by the publisher.
         * This allows for pagination, but with the expectation that reader software is not required
         * to use it and probably won’t use it very often
         *
         * @param nextURL the URL of a feed that provides the next n items
         * @return Builder
         */
        @NonNull
        public Builder nextUrl(@NonNull String nextURL) {
            this.feed.setNextURL(nextURL);
            return this;
        }

        /**
         * The URL of an image for the feed suitable to be used in a timeline, much the way an
         * avatar might be used. It should be square and relatively large — such as 512 x 512
         * pixels
         *
         * @param icon the URL of an image for the feed suitable to be used in a timeline
         * @return Builder
         */
        @NonNull
        public Builder icon(@NonNull String icon) {
            this.feed.setIcon(icon);
            return this;
        }

        /**
         * The URL of an image for the feed suitable to be used in a source list. It should be
         * square and relatively small, but not smaller than 64 x 64 pixels
         *
         * @param favicon the URL of an image for the feed suitable to be used in a source list
         * @return Builder
         */
        @NonNull
        public Builder favicon(@NonNull String favicon) {
            this.feed.setFavicon(favicon);
            return this;
        }

        /**
         * Content of the feed.
         *
         * @param item content of the feed
         * @return Builder
         */
        @NonNull
        public Builder item(@NonNull JsonFeedItem item) {
            this.feed.addItem(item);
            return this;
        }

        /**
         * Adds an author to the feed.
         *
         * @param author An author of the feed
         * @return Builder
         */
        @NonNull
        public Builder author(@NonNull JsonFeedAuthor author) {
            this.feed.addAuthor(author);
            return this;
        }

        /**
         * The primary language for the feed in the format specified in RFC 5646.
         *
         * @param language the primary language for the feed
         * @return Builder
         */
        @NonNull
        public Builder language(@NonNull RssLanguage language) {
            this.feed.setLanguage(language.getLanguageCode());
            return this;
        }

        /**
         * The primary language for the feed in the format specified in RFC 5646.
         *
         * @param language the primary language for the feed
         * @return Builder
         */
        @NonNull
        public Builder language(@NonNull String language) {
            this.feed.setLanguage(language);
            return this;
        }

        /**
         * Says whether or not the feed is finished — that is, whether or not it will ever update
         * again.
         *
         * @param expired says whether or not the feed is finished
         * @return Builder
         */
        @NonNull
        public Builder expired(@NonNull Boolean expired) {
            this.feed.setExpired(expired);
            return this;
        }

        /**
         * Describes endpoints that can be used to subscribe to real-time notifications from the
         * publisher of this feed.
         *
         * @param hub Describes endpoints that can be used to subscribe to real-time notifications
         * @return Builder
         */
        @NonNull
        public Builder hub(@NonNull JsonHub hub) {
            this.feed.addHub(hub);
            return this;
        }

        /**
         *
         * @param items Feed items
         * @return The Builder.
         */
        @NonNull
        public Builder items(@NonNull List items) {
            this.feed.setItems(items);
            return this;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy