nl.gridshore.nosapi.impl.DataProviderImpl.java Source code

Java tutorial

Introduction

Here is the source code for nl.gridshore.nosapi.impl.DataProviderImpl.java

Source

/*
 * Copyright (c) 2011. Gridshore
 * 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
 *
 * http://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 nl.gridshore.nosapi.impl;

import nl.gridshore.nosapi.*;
import nl.gridshore.nosapi.mapping.*;
import nl.gridshore.nosapi.mapping.DayGuide;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>The default and for now only implementation of the DataProvider interface. This implementation is based on the
 * RESTTemplate from the spring framework. You can provide your own instance of the RESTTemplate. The default
 * RESTTemplate makes use of a specific ErrorHandler <code>NosApiResponseErrorHandler</code>.</p>
 * <p>This class is based on the NOS api version v1</p>
 *
 * @author Jettro Coenradie
 */
public class DataProviderImpl implements DataProvider {
    private final static Logger logger = LoggerFactory.getLogger(DataProviderImpl.class);
    private final static DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");

    private String serverBaseUrl = "http://open.nos.nl/v2/";

    private final String apiKey;
    private final RestTemplate restTemplate;

    public DataProviderImpl(String apiKey) {
        this(apiKey, new RestTemplate());
        restTemplate.setErrorHandler(new NosApiResponseErrorHandler());
    }

    public DataProviderImpl(String apiKey, RestTemplate restTemplate) {
        Assert.hasText(apiKey);
        Assert.notNull(restTemplate);
        this.restTemplate = restTemplate;
        this.apiKey = apiKey;
    }

    @Override
    public nl.gridshore.nosapi.Version obtainVersion() {
        VersionWrapper versionWrapper = restTemplate.getForObject(
                serverBaseUrl + "index/version/key/{apikey}/output/json", VersionWrapper.class, apiKey);
        return new nl.gridshore.nosapi.Version(versionWrapper.getVersions().get(0).getBuild(),
                versionWrapper.getVersions().get(0).getVersion());
    }

    @Override
    public List<nl.gridshore.nosapi.Article> obtainLatestNewsArticles() {
        return obtainLatestItemPerCategory("nieuws/", "article", LatestArticle.class);
    }

    @Override
    public List<nl.gridshore.nosapi.Article> obtainLatestSportsNewsArticles() {
        return obtainLatestItemPerCategory("sport/", "article", LatestArticle.class);
    }

    @Override
    public List<nl.gridshore.nosapi.Article> obtainLatestNewsVideos() {
        return obtainLatestItemPerCategory("nieuws/", "video", LatestVideo.class);
    }

    @Override
    public List<nl.gridshore.nosapi.Article> obtainLatestSportsNewsVideos() {
        return obtainLatestItemPerCategory("sport/", "video", LatestVideo.class);
    }

    @Override
    public List<nl.gridshore.nosapi.Article> obtainLatestNewsAudio() {
        return obtainLatestItemPerCategory("nieuws/", "audio", LatestAudio.class);
    }

    @Override
    public List<nl.gridshore.nosapi.Article> obtainLatestSportsNewsAudio() {
        return obtainLatestItemPerCategory("sport/", "audio", LatestAudio.class);
    }

    @Override
    public SearchResults searchForDocuments(String queryString) {
        return this.searchForDocuments(queryString, null);
    }

    @Override
    public SearchResults searchForDocuments(String queryString, SearchSort sort) {
        Assert.notNull(queryString);
        String searchSort;
        if (sort == null) {
            searchSort = SearchSort.SCORE.toString().toLowerCase();
        } else {
            searchSort = sort.toString().toLowerCase();
        }
        String url = serverBaseUrl + "search/query/key/{apikey}/output/json/q/{search}/sort/{sort}";
        SearchWrapper searchResults;
        try {
            searchResults = restTemplate.getForObject(url, SearchWrapper.class, apiKey, queryString, searchSort);
        } catch (HttpMessageNotReadableException e) {
            logger.error(
                    "There might be a problem on the server while searching for documents. Usually this exception "
                            + "is thrown if the json returned has a wrong format. The used query is {}",
                    queryString, e.getMostSpecificCause());
            throw new UnknownClientException(
                    "Most probably an incorrect response was received from the nos data api",
                    e.getMostSpecificCause());
        }
        ArrayList<nl.gridshore.nosapi.mapping.Document> documents = searchResults.getSearch().get(0).getDocuments();
        List<nl.gridshore.nosapi.Document> foundDocuments = new ArrayList<nl.gridshore.nosapi.Document>();
        for (nl.gridshore.nosapi.mapping.Document document : documents) {
            foundDocuments.add(new nl.gridshore.nosapi.Document(document.getId(), document.getType(),
                    document.getTitle(), document.getDescription(), document.getCategory(),
                    document.getSubCategory(), document.getPublished(), document.getLastUpdate(),
                    document.getLink(), document.getThumbnail(), document.getScore(), document.getKeywords()));
        }

        ArrayList<nl.gridshore.nosapi.mapping.Keyword> keywords = searchResults.getSearch().get(0).getKeywords();
        List<nl.gridshore.nosapi.Keyword> foundKeywords = new ArrayList<nl.gridshore.nosapi.Keyword>();
        for (nl.gridshore.nosapi.mapping.Keyword keyword : keywords) {
            foundKeywords.add(new nl.gridshore.nosapi.Keyword(keyword.getTag(), keyword.getCount()));
        }

        return new SearchResults(foundDocuments, foundKeywords);
    }

    @Override
    public List<nl.gridshore.nosapi.DayGuide> obtainTVGuide() {
        return obtainGuide("tv");
    }

    @Override
    public List<nl.gridshore.nosapi.DayGuide> obtainRadioGuide() {
        return obtainGuide("radio");
    }

    @Override
    public List<nl.gridshore.nosapi.DayGuide> obtainTVGuide(TVChannel channel, String startDate, String endDate) {
        String channelName = (channel != null) ? channel.toString() : null;
        return obtainGuide(channelName, startDate, endDate, "tv");
    }

    @Override
    public List<nl.gridshore.nosapi.DayGuide> obtainRadioGuide(RadioChannel channel, String startDate,
            String endDate) {
        String channelName = (channel != null) ? channel.toString() : null;
        return obtainGuide(channelName, startDate, endDate, "radio");
    }

    private List<nl.gridshore.nosapi.DayGuide> obtainGuide(String channel, String startDate, String endDate,
            String type) {
        validateStartEndDate(startDate, endDate);

        StringBuilder builder = new StringBuilder();
        builder.append(serverBaseUrl);
        builder.append("guide/{type}/key/{apikey}/output/json");

        List<Comparable> arguments = new ArrayList<Comparable>();
        arguments.add(type);
        arguments.add(apiKey);

        if (channel != null) {
            builder.append("/channel/{channel}");
            arguments.add(channel);
        }
        if (StringUtils.hasText(startDate) && StringUtils.hasText(endDate)) {
            builder.append("/start/{startdate}");
            arguments.add(startDate);

            builder.append("/end/{enddate}");
            arguments.add(endDate);
        }

        Guide guide = restTemplate.getForObject(builder.toString(), Guide.class, arguments.toArray());

        return mapJSONGuideToOurGuide(guide);
    }

    private void validateStartEndDate(String startDate, String endDate) {
        if (StringUtils.hasText(startDate) || StringUtils.hasText(endDate)) {
            if (!StringUtils.hasText(startDate) || !StringUtils.hasText(endDate)) {
                throw new IllegalArgumentException(
                        "When providing a start or end data, the other one needs to be provided as well.");
            }
            DateTime startTime = formatter.parseDateTime(startDate);
            DateTime endTime = formatter.parseDateTime(endDate);
            if (endTime.isBefore(startTime)) {
                throw new IllegalArgumentException("Start date must be before end date");
            }
        }
    }

    private List<nl.gridshore.nosapi.DayGuide> obtainGuide(String type) {
        String url = serverBaseUrl + "guide/{type}/key/{apikey}/output/json";
        Guide guide = restTemplate.getForObject(url, Guide.class, type, apiKey);
        return mapJSONGuideToOurGuide(guide);
    }

    private List<nl.gridshore.nosapi.DayGuide> mapJSONGuideToOurGuide(Guide guide) {
        ArrayList<DayGuide> dayGuides = guide.getGuide().get(0);
        List<nl.gridshore.nosapi.DayGuide> days = new ArrayList<nl.gridshore.nosapi.DayGuide>();
        for (DayGuide dayGuide : dayGuides) {
            List<Program> programs = new ArrayList<Program>();
            for (GuideItem guideItem : dayGuide.getGuide()) {
                programs.add(new Program(guideItem.getId(), guideItem.getTitle(), guideItem.getType(),
                        guideItem.getGenre(), guideItem.getDescription(), guideItem.getStartTime(),
                        guideItem.getEndTime(), new Channel(guideItem.getChannelCode(), guideItem.getChannelIcon(),
                                guideItem.getChannelName())));
            }
            days.add(new nl.gridshore.nosapi.DayGuide(dayGuide.getDate(), programs));
        }
        return days;
    }

    private List<nl.gridshore.nosapi.Article> obtainLatestItemPerCategory(String category, String type,
            Class<? extends LatestItem> clazz) {
        String url = serverBaseUrl + "latest/" + type + "/key/{apikey}/output/json/category/" + category;
        LatestItem latestItem = restTemplate.getForObject(url, clazz, apiKey);

        List<nl.gridshore.nosapi.Article> articles = new ArrayList<nl.gridshore.nosapi.Article>();
        for (nl.gridshore.nosapi.mapping.Article article : latestItem.getItems().get(0)) {
            articles.add(new nl.gridshore.nosapi.Article(article.getId(), article.getType(), article.getTitle(),
                    article.getDescription(), article.getLink(), article.getKeywords(), article.getLastUpdate(),
                    article.getPublished(), article.getThumbnail_m(), article.getThumbnail_s(),
                    article.getThumbnail_xs(), article.getEmbedCode()));
        }
        return articles;
    }
}