/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.weather.internal.parser; import java.io.InputStream; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.reflect.FieldUtils; import org.openhab.binding.weather.internal.converter.Converter; import org.openhab.binding.weather.internal.converter.property.PressureTrendConverter; import org.openhab.binding.weather.internal.metadata.MetadataHandler; import org.openhab.binding.weather.internal.metadata.ProviderMappingInfo; import org.openhab.binding.weather.internal.model.Atmosphere; import org.openhab.binding.weather.internal.model.Forecast; import org.openhab.binding.weather.internal.model.Precipitation; import org.openhab.binding.weather.internal.model.ProviderName; import org.openhab.binding.weather.internal.model.Temperature; import org.openhab.binding.weather.internal.model.Weather; import org.openhab.binding.weather.internal.model.Wind; import org.openhab.binding.weather.internal.utils.PropertyResolver; import org.openhab.binding.weather.internal.utils.PropertyUtils; import org.openhab.binding.weather.internal.utils.UnitUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Common base class for all weather parsers. * * @author Gerhard Riegler * @since 1.6.0 */ public abstract class AbstractWeatherParser implements WeatherParser { private static final Logger logger = LoggerFactory.getLogger(AbstractWeatherParser.class); private static final String[] EMPTY_VALUES = new String[] { "NA", "N/A", "--", "" }; private MetadataHandler metadataHandler = MetadataHandler.getInstance(); /** * {@inheritDoc} */ @Override public void parseInto(InputStream is, Weather weather) throws Exception { postProcessEach(weather); for (Forecast forecast : weather.getForecast()) { postProcessEach(forecast); } postProcess(weather); } /** * {@inheritDoc} */ @Override public void setValue(Weather weather, String propertyName, String value) { ProviderMappingInfo providerMappingInfo = metadataHandler.getProviderMappingInfo(weather.getProvider(), propertyName); if (providerMappingInfo != null) { logger.trace("Setting property '{} ({})' with value '{}'", providerMappingInfo.getTarget(), propertyName, value); try { String targetProperty = providerMappingInfo.getTarget(); Object target = PropertyUtils.getNestedObject(weather, targetProperty); String objectProperty = PropertyResolver.last(targetProperty); String preparedValue = stripEmptyValues(value); Converter<?> converter = providerMappingInfo.getConverter(); Object valueToSet = preparedValue == null ? null : converter.convert(preparedValue); if (valueToSet != null) { FieldUtils.writeField(target, objectProperty, valueToSet, true); } } catch (Exception ex) { logger.warn("{}: Error setting property '{}' with value '{}' and converter {}", weather.getProvider(), propertyName, value, providerMappingInfo.getConverter().getType()); } } else { logger.trace("Property not mapped: '{}' with value '{}'", propertyName, value); } } /** * {@inheritDoc} */ @Override public Weather startIfForecast(Weather weather, String propertyName) { if (metadataHandler.isForecast(weather.getProvider(), propertyName)) { return new Forecast(weather.getProvider()); } return weather; } /** * {@inheritDoc} */ @Override public boolean endIfForecast(Weather weather, Weather forecast, String propertyName) { if (metadataHandler.isForecast(forecast.getProvider(), propertyName)) { Forecast fc = (Forecast) forecast; fc.setDay(weather.getForecast().size()); weather.getForecast().add(fc); return true; } return false; } /** * Removes empty value markers. */ protected String stripEmptyValues(String value) { for (String string : EMPTY_VALUES) { if (StringUtils.equalsIgnoreCase(value, string)) { return null; } } return value; } /** * {@inheritDoc} */ @Override public void postProcessEach(Weather weather) throws Exception { Temperature temp = weather.getTemperature(); if (temp.getCurrent() != null && weather instanceof Forecast) { temp.setCurrent(null); } Atmosphere atm = weather.getAtmosphere(); if (temp.getFeel() == null && temp.getCurrent() != null && atm.getHumidity() != null) { Double humidex = UnitUtils.getHumidex(temp.getCurrent(), atm.getHumidity()); temp.setFeel(humidex); } Wind wind = weather.getWind(); if (wind.getDirection() == null && wind.getDegree() != null) { String direction = UnitUtils.getWindDirection(wind.getDegree()); wind.setDirection(direction); } Precipitation precip = weather.getPrecipitation(); if ((weather.getProvider() == ProviderName.FORECASTIO && StringUtils.equalsIgnoreCase("snow", precip.getType())) || (weather.getProvider() == ProviderName.METEOBLUE && StringUtils.equalsIgnoreCase("1", precip.getType()))) { precip.setSnow(precip.getRain()); precip.setRain(null); } if (precip.getSnow() == null) { precip.setSnow(0.0); } if (precip.getRain() == null) { precip.setRain(0.0); } CommonIdHandler.getInstance().setCommonId(weather); } /** * {@inheritDoc} */ @Override public void postProcess(Weather weather) throws Exception { if (weather.getAtmosphere().getPressureTrend() == null) { Double currentPressure = weather.getAtmosphere().getPressure(); if (currentPressure != null && weather.getForecast().size() > 0) { Double fcPressure = weather.getForecast().get(0).getAtmosphere().getPressure(); if (fcPressure != null) { if (fcPressure > currentPressure) { weather.getAtmosphere().setPressureTrend(PressureTrendConverter.TREND_UP); } else if (fcPressure < currentPressure) { weather.getAtmosphere().setPressureTrend(PressureTrendConverter.TREND_DOWN); } else { weather.getAtmosphere().setPressureTrend(PressureTrendConverter.TREND_EQUAL); } } } } } }