net.solarnetwork.node.weather.nz.metservice.MetserviceSupport.java Source code

Java tutorial

Introduction

Here is the source code for net.solarnetwork.node.weather.nz.metservice.MetserviceSupport.java

Source

/* ==================================================================
 * MetserviceSupport.java - Oct 18, 2011 2:47:44 PM
 * 
 * Copyright 2007-2011 SolarNetwork.net Dev Team
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 of 
 * the License, or (at your option) any later version.
 * 
 * This program 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 
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
 * 02111-1307 USA
 * ==================================================================
 */

package net.solarnetwork.node.weather.nz.metservice;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.solarnetwork.node.domain.Datum;
import net.solarnetwork.node.support.UnicodeReader;
import net.solarnetwork.node.support.XmlServiceSupport;
import org.springframework.util.FileCopyUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Base class to support MetService Day and Weather data sources.
 * 
 * <p>
 * The configurable properties of this class are:
 * </p>
 * 
 * <dl class="class-properties">
 * <dt>baseUrl</dt>
 * <dd>The base URL for queries to MetService. Defaults to
 * {@link #DEFAULT_BASE_URL}.</dd>
 * 
 * <dt>objectMapper</dt>
 * <dd>The {@link ObjectMapper} to use for parsing JSON.</dd>
 * </dl>
 * 
 * @param T
 *        the datum type
 * @author matt
 * @version 1.4
 */
public abstract class MetserviceSupport<T extends Datum> extends XmlServiceSupport {

    /** The default value for the {@code baseUrl} property. */
    public static final String DEFAULT_BASE_URL = "http://www.metservice.com/publicData";

    /** A key to use for the "last datum" in the local cache. */
    protected static final String LAST_DATUM_CACHE_KEY = "last";

    private final Map<String, T> datumCache;
    private String baseUrl;
    private ObjectMapper objectMapper;

    public MetserviceSupport() {
        datumCache = new ConcurrentHashMap<String, T>(2);
        baseUrl = DEFAULT_BASE_URL;
    }

    /**
     * an InputStream as Unicode text and return as a String.
     * 
     * @param in
     *        the InputStream to read
     * @return the text
     * @throws IOException
     *         if an IO error occurs
     */
    protected String readUnicodeInputStream(InputStream in) throws IOException {
        UnicodeReader reader = new UnicodeReader(in, null);
        String data = FileCopyUtils.copyToString(reader);
        reader.close();
        return data;
    }

    /**
     * Parse a Date from an attribute value.
     * 
     * <p>
     * If the date cannot be parsed, <em>null</em> will be returned.
     * </p>
     * 
     * @param key
     *        the attribute key to obtain from the {@code data} Map
     * @param data
     *        the attributes
     * @param dateFormat
     *        the date format to use to parse the date string
     * @return the parsed {@link Date} instance, or <em>null</em> if an error
     *         occurs or the specified attribute {@code key} is not available
     */
    protected Date parseDateAttribute(String key, JsonNode data, SimpleDateFormat dateFormat) {
        Date result = null;
        if (data != null) {
            JsonNode node = data.get(key);
            if (node != null) {
                try {
                    result = dateFormat.parse(node.asText());
                } catch (ParseException e) {
                    log.debug("Error parsing date attribute [{}] value [{}] using pattern {}: {}",
                            new Object[] { key, data.get(key), dateFormat.toPattern(), e.getMessage() });
                }
            }
        }
        return result;
    }

    /**
     * Parse a Double from an attribute value.
     * 
     * <p>
     * If the Double cannot be parsed, <em>null</em> will be returned.
     * </p>
     * 
     * @param key
     *        the attribute key to obtain from the {@code data} Map
     * @param data
     *        the attributes
     * @return the parsed {@link Double}, or <em>null</em> if an error occurs or
     *         the specified attribute {@code key} is not available
     */
    protected Double parseDoubleAttribute(String key, JsonNode data) {
        Double num = null;
        if (data != null) {
            JsonNode node = data.get(key);
            if (node != null) {
                try {
                    num = Double.valueOf(node.asText());
                } catch (NumberFormatException e) {
                    log.debug("Error parsing double attribute [{}] value [{}]: {}",
                            new Object[] { key, data.get(key), e.getMessage() });
                }
            }
        }
        return num;
    }

    /**
     * Parse a FLoat from an attribute value.
     * 
     * <p>
     * If the Float cannot be parsed, <em>null</em> will be returned.
     * </p>
     * 
     * @param key
     *        the attribute key to obtain from the {@code data} node
     * @param data
     *        the attributes
     * @return the parsed {@link Float}, or <em>null</em> if an error occurs or
     *         the specified attribute {@code key} is not available
     */
    protected Float parseFloatAttribute(String key, JsonNode data) {
        Float num = null;
        if (data != null) {
            JsonNode node = data.get(key);
            if (node != null) {
                try {
                    num = Float.valueOf(node.asText());
                } catch (NumberFormatException e) {
                    log.debug("Error parsing float attribute [{}] value [{}]: {}",
                            new Object[] { key, data.get(key), e.getMessage() });
                }
            }
        }
        return num;
    }

    /**
     * Parse a Integer from an attribute value.
     * 
     * <p>
     * If the Integer cannot be parsed, <em>null</em> will be returned.
     * </p>
     * 
     * @param key
     *        the attribute key to obtain from the {@code data} node
     * @param data
     *        the attributes
     * @return the parsed {@link Integer}, or <em>null</em> if an error occurs
     *         or the specified attribute {@code key} is not available
     */
    protected Integer parseIntegerAttribute(String key, JsonNode data) {
        Integer num = null;
        if (data != null) {
            JsonNode node = data.get(key);
            if (node != null) {
                try {
                    num = Integer.valueOf(node.asText());
                } catch (NumberFormatException e) {
                    log.debug("Error parsing integer attribute [{}] value [{}]: {}",
                            new Object[] { key, data.get(key), e.getMessage() });
                }
            }
        }
        return num;
    }

    /**
     * Get a cache to support queries resulting in unchanged data.
     * 
     * @return
     */
    protected Map<String, T> getDatumCache() {
        return datumCache;
    }

    public String getBaseUrl() {
        return baseUrl;
    }

    public void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }

    public ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

}