se.vgregion.domain.infrastructure.webservice.RestCalendarEventsRepository.java Source code

Java tutorial

Introduction

Here is the source code for se.vgregion.domain.infrastructure.webservice.RestCalendarEventsRepository.java

Source

/**
 * Copyright 2010 Vstra Gtalandsregionen
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of version 2.1 of the GNU Lesser General Public
 *   License as published by the Free Software Foundation.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the
 *   Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 *   Boston, MA 02111-1307  USA
 *
 */

/**
 *
 */
package se.vgregion.domain.infrastructure.webservice;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestClientException;
import se.vgregion.core.domain.calendar.CalendarEvents;
import se.vgregion.core.domain.calendar.CalendarEventsPeriod;
import se.vgregion.core.domain.calendar.CalendarEventsRepository;
import se.vgregion.core.domain.calendar.CalendarItem;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

/**
 * Implementation of {@link CalendarEventsRepository} which is used for restfull requests against service endpoint.
 * The service url is specified with the following pattern:
 * http://<host>?userid=<userid>&year=<year>&month=<month>&day=<day>&period=<period>
 *
 * @author Anders Asplund - Callista Enterprise
 */
public class RestCalendarEventsRepository implements CalendarEventsRepository {

    private static final Logger LOGGER = LoggerFactory.getLogger(RestCalendarEventsRepository.class);
    private String serviceUrl;

    /**
     * Constructs a RestCalendarEventsRepository for a restfull reqest to the specified service endpoint.
     *
     */
    public RestCalendarEventsRepository() {
    }

    /**
     * Sets the service endpoint.
     *
     * @param serviceEndpoint the service endpoint
     */
    public void setServiceEndpoint(String serviceEndpoint) {
        this.serviceUrl = serviceEndpoint + "userid=%s&year=%s&month=%s&day=%s&period=%s";
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * se.vgregion.core.domain.calendar.CalendarEventsRepository#findCalendarEventsByCalendarPeriod(java.lang.String
     * , se.vgregion.core.domain.calendar.CalendarEventsPeriod)
     */
    @Override
    public CalendarEvents findCalendarEventsByCalendarPeriod(String userId, CalendarEventsPeriod period) {
        CalendarEvents events = CalendarEvents.EMPTY_CALENDAR_EVENTS;
        try {
            LOGGER.debug("Calling the following web service: {}", serviceUrl);
            LOGGER.debug("Paramters sent to web service: userid={}, year={}, month={}, day={}, period={}",
                    new Object[] { userId, period.getStartDate().getYear(), period.getStartDate().getMonthOfYear(),
                            period.getStartDate().getDayOfMonth(), period.getDays().getDays() });

            String requestUrl = String.format(serviceUrl, userId, period.getStartDate().getYear(),
                    period.getStartDate().getMonthOfYear(), period.getStartDate().getDayOfMonth(),
                    period.getDays().getDays());

            events = getCalendarEventsFromUrl(requestUrl);

        } catch (RestClientException e) {
            LOGGER.error("Unable to retreive information from web service: {}. CalendarEventPeriod={}",
                    new Object[] { serviceUrl, period });
            LOGGER.error("Web service exception", e);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            LOGGER.error("Unable to retreive information from web service: {}. CalendarEventPeriod={}",
                    new Object[] { serviceUrl, period });
            LOGGER.error("Web service exception", e);
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
        return events;
    }

    protected CalendarEvents getCalendarEventsFromUrl(String requestUrl) throws IOException, JAXBException {
        InputStream inputStream = null;
        BufferedInputStream bis = null;
        try {

            URL url = new URL(requestUrl);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            inputStream = urlConnection.getInputStream();
            bis = new BufferedInputStream(inputStream);

            CalendarEvents calendarEvents = extractCalendarEvents(bis);

            if (calendarEvents != null && calendarEvents.getCalendarItems() != null) {
                List<CalendarItem> calendarItems = calendarEvents.getCalendarItems();
                for (CalendarItem item : calendarItems) {
                    String calendarType = item.getCalendarType();
                    if (calendarType != null) {
                        item.setCalendarType(item.getCalendarType().replace("Noteskalender", "Notes"));
                    }
                }
            }

            return calendarEvents;
        } finally {
            closeClosables(bis, inputStream);
        }
    }

    private static void closeClosables(Closeable... closables) {
        for (Closeable closeable : closables) {
            if (closeable != null) {
                try {
                    closeable.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        }
    }

    // This method uses either UTF-8 or ISO-8859-1 to decode depending on which method results in the most Swedish
    // characters.
    private CalendarEvents extractCalendarEvents(InputStream bis) throws IOException, JAXBException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buf = new byte[4096];
        int n;
        while ((n = bis.read(buf)) != -1) {
            baos.write(buf, 0, n);
        }

        String inUtf8 = new String(baos.toByteArray(), "UTF-8");
        String inIso8859 = new String(baos.toByteArray(), "ISO-8859-1");
        int numberSwedishCharactersFromUtf8 = StringUtils.countMatches(inUtf8, "")
                + StringUtils.countMatches(inUtf8, "") + StringUtils.countMatches(inUtf8, "");
        int numberSwedishCharactersFromIso8859 = StringUtils.countMatches(inIso8859, "")
                + StringUtils.countMatches(inIso8859, "") + StringUtils.countMatches(inIso8859, "");

        String toUse;
        if (numberSwedishCharactersFromIso8859 > numberSwedishCharactersFromUtf8) {
            toUse = inIso8859;
        } else {
            toUse = inUtf8;
        }

        JAXBContext jaxbContext = JAXBContext.newInstance(CalendarEvents.class);
        return (CalendarEvents) jaxbContext.createUnmarshaller().unmarshal(new StringReader(toUse));
    }

}