Android Open Source - Blue-Sky-Weather Forecast Parser






From Project

Back to project page Blue-Sky-Weather.

License

The source code is released under:

GNU General Public License

If you think the Android project Blue-Sky-Weather listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Copyright (C) 2011 David Schonert/*from w  ww  .j a  va  2s . com*/
 *
 * This file is part of BlueSky.
 *
 * BlueSky 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 3 of the License, or
 * any later version.
 *
 * BlueSky 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 BlueSky.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.SyntheticCode.BlueSkyWeather.parsers;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import com.SyntheticCode.BlueSkyWeather.CityData;
import com.SyntheticCode.BlueSkyWeather.ForecastData;
import com.SyntheticCode.BlueSkyWeather.ForecastData.ForecastDataObject;
import android.content.Context;
import android.util.Log;
import android.util.Xml;

/**
 * @author David
 *
 */
public class ForecastParser extends BaseFeedParser {
  static final String FORECAST_SHORT = "txt_forecast";
  static final String FORECAST_EXTENDED = "simpleforecast";
  static final String FORECAST_DAY = "forecastday";
  
  static final String SHORT_INDEX = "period";
  static final String SHORT_ICON = "icon";
  static final String SHORT_TITLE = "title";
  static final String SHORT_FORECAST = "fcttext";
  
  static final String EXTENDED_INDEX = "period";
  static final String EXTENDED_ICON = "icon";
  static final String EXTENDED_DATE = "date";
  static final String EXTENDED_DATE_DAY = "day";
  static final String EXTENDED_DATE_MONTH = "month";
  static final String EXTENDED_DATE_WEEKDAY = "weekday";
  static final String EXTENDED_HIGH = "high";
  static final String EXTENDED_TEMP_F = "fahrenheit";
  static final String EXTENDED_TEMP_C = "celsius";
  static final String EXTENDED_LOW = "low";
  static final String EXTENDED_CONDITION = "conditions";
  
  /** Tags **/
  // Forecast period title
  static final String PERIOD_ROOT = "time-layout";
  static final String PERIOD_LAYOUT_KEY = "layout-key";
  static final String PERIOD = "start-valid-time";
  
  // Data
  static final String PARAM_ROOT = "parameters";
  static final String TEMP_ROOT = "temperature";
  static final String CONDITION_ROOT = "weather";
  static final String ICON_ROOT = "conditions-icon";
  static final String FORECAST_ROOT = "wordedForecast";
  static final String PARAM_VALUE = "value";
  static final String CONDITION = "weather-conditions";
  static final String ICON = "icon-link";
  static final String FORECAST_TEXT = "text";
  
  /** Attributes **/
  static final String PERIOD_TITLE = "period-name";
  static final String TEMP_TYPE = "type";
  static final String CONDITION_VALUE = "weather-summary";
  static final String LAYOUT_TYPE = "time-layout";
  
  private ForecastData forecast;

  /**
   * Creator builds the XML feed url. Uses the calling Activity's context to get the string from resources.
   * @param parentContext : Parent of this object (needs to have a context)
   * @param location : Location to get forecast for {"city, state"}
   * @throws UnsupportedEncodingException
   */
  public ForecastParser(Context parentContext, CityData location) throws UnsupportedEncodingException {
    // Build the feed url from the query and the geoLookup url
    // Use URLEncoder.encode() to remove invalid characters from query
    super(urlBuilder(location));
  }
  
  private static String urlBuilder(CityData city) throws UnsupportedEncodingException {
    final String base = "http://forecast.weather.gov/MapClick.php?";
    final String cityTag = "CityName=";
    final String stateTag = "state=";
    final String siteTag = "site=HNX";
    final String latTag = "textField1=";
    final String lonTag = "textField2=";
    final String typeTag = "FcstType=dwml";
    
    String url = base;
    url += cityTag + URLEncoder.encode(city.getCity(), "UTF-8") + "&";
    url += stateTag + URLEncoder.encode(city.getState(), "UTF-8") + "&";
    url += siteTag + "&";
    url += latTag + URLEncoder.encode(city.getLat(), "UTF-8") + "&";
    url += lonTag + URLEncoder.encode(city.getLon(), "UTF-8") + "&";
    url += typeTag;
    
    Log.v("BlueSky", "NWS url = " + url);
    
    return url;
  }

  /* (non-Javadoc)
   * @see synthetic.code.weather.BlueSky.parsers.BaseFeedParser#parse()
   */
  @Override
  public ForecastData parse() throws RuntimeException {
    abort = false;
    forecast = new ForecastData();
    
    XmlPullParser parser = Xml.newPullParser();
    try {
      // auto-detect the encoding from the stream
      parser.setInput(this.getInputStream(), null);
      
      int eventType = parser.getEventType();
      
      int periodCount = 0;
      
      while(eventType != XmlPullParser.END_DOCUMENT && !abort) {
        String tagName = null;
        
        switch(eventType) {
        case XmlPullParser.START_TAG:
          tagName = parser.getName();
          
          if(tagName.equalsIgnoreCase(PERIOD_ROOT)) {
            Log.v("BlueSky", "periodCount = " + periodCount);
            parser = parsePeriods(parser);
            periodCount++;
          }
          else if(tagName.equalsIgnoreCase(TEMP_ROOT)) {
            parser = parseTemperatures(parser);
          }
          else if(tagName.equalsIgnoreCase(CONDITION_ROOT)) {
            parser = parseConditions(parser);
          }
          else if(tagName.equalsIgnoreCase(ICON_ROOT)) {
            parser = parseIcons(parser);
          }
          else if(tagName.equalsIgnoreCase(FORECAST_ROOT)) {
            parser = parseForecast(parser);
          }
          break;
          
        case XmlPullParser.END_TAG:
          tagName = parser.getName();
          break;
        }
        
        eventType = parser.next();
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    
    return forecast;
  }
  
  private XmlPullParser parsePeriods(XmlPullParser parser) throws XmlPullParserException, IOException {
    String tagName = null;
    boolean done = false;
    int eventType = 0;
    String attribute = null;
    String layoutKey = "";
    ForecastData.ForecastDataObject period = null; // pointer to period to write to
    
    while(eventType != XmlPullParser.END_DOCUMENT && !done && !abort) {
      // Do the parse at the start so that parser is in correct location on exit
      eventType = parser.next();
      
      switch(eventType) {
      case XmlPullParser.START_TAG:
        tagName = parser.getName();
        // Get the layout key
        if(tagName.equalsIgnoreCase(PERIOD_LAYOUT_KEY)) {
          layoutKey = parser.nextText();
        }
        // Get all the period names
        else if(tagName.equalsIgnoreCase(PERIOD)) {
          attribute = parser.getAttributeValue(null, PERIOD_TITLE);
          if(attribute != null) {
            // Create the period object
            if(period == null) {
              period = new ForecastData.ForecastDataObject();
              period.timeLayout = layoutKey;
            }
            
            period.data.add(attribute);
          }
        }
        
        break;
        
      case XmlPullParser.END_TAG:
        tagName = parser.getName();
        if(tagName.equalsIgnoreCase(PERIOD_ROOT)) {
          // end the loop when the closing root is reached
          done = true;
        }
        break;
      }
    }
    
    // If period was created then add it to the list of periods
    if(period != null) {
      forecast.periods.add(period);
    }
    
    if(period != null) {
      period.print("Period " + forecast.periods.size());
    }
    
    return parser;
  }
  
  private XmlPullParser parseTemperatures(XmlPullParser parser) throws XmlPullParserException, IOException {
    final String min = "minimum";
    String tagName = null;
    boolean done = false;
    int eventType = 0;
    
    ForecastDataObject temperature = null;

    // Check if the temperatures are max or min
    String type = parser.getAttributeValue(null, TEMP_TYPE);
    boolean isMin = min.equalsIgnoreCase(type);
    
    // Set the pointer to the correct temperature object
    if(isMin) {
      temperature = forecast.temperatureMin;
    }
    else {
      temperature = forecast.temperatureMax;
    }
    
    // Get the time layout
    temperature.timeLayout = parser.getAttributeValue(null, LAYOUT_TYPE);
    
    while(eventType != XmlPullParser.END_DOCUMENT && !done && !abort) {
      // Do the parse at the start so that parser is in correct location on exit
      eventType = parser.next();
      
      switch(eventType) {
      case XmlPullParser.START_TAG:
        tagName = parser.getName();
        // Get all the temperature values
        if(tagName.equalsIgnoreCase(PARAM_VALUE)) {
          temperature.data.add(parser.nextText());
        }
        
        break;
        
      case XmlPullParser.END_TAG:
        tagName = parser.getName();
        if(tagName.equalsIgnoreCase(TEMP_ROOT)) {
          // end the loop when the closing root is reached
          done = true;
        }
        break;
      }
    }
    
    if(isMin) {
      temperature.print("Temp Min");
    }
    else {
      temperature.print("Temp Max");
    }
    
    return parser;
  }
  
  private XmlPullParser parseConditions(XmlPullParser parser) throws XmlPullParserException, IOException {
    String tagName = null;
    boolean done = false;
    int eventType = 0;
    String attribute = null;
    
    // Get the time layout
    forecast.weatherCondition.timeLayout = parser.getAttributeValue(null, LAYOUT_TYPE);
    
    while(eventType != XmlPullParser.END_DOCUMENT && !done && !abort) {
      // Do the parse at the start so that parser is in correct location on exit
      eventType = parser.next();
      
      switch(eventType) {
      case XmlPullParser.START_TAG:
        tagName = parser.getName();
        // Get all the weather conditions
        if(tagName.equalsIgnoreCase(CONDITION)) {
          attribute = parser.getAttributeValue(null, CONDITION_VALUE);
          if(attribute != null) {
            forecast.weatherCondition.data.add(attribute);
          }
        }
        
        break;
        
      case XmlPullParser.END_TAG:
        tagName = parser.getName();
        if(tagName.equalsIgnoreCase(CONDITION_ROOT)) {
          // end the loop when the closing root is reached
          done = true;
        }
        break;
      }
    }
    
    forecast.weatherCondition.print("Weather");
    
    return parser;
  }
  
  private XmlPullParser parseIcons(XmlPullParser parser) throws XmlPullParserException, IOException {
    String tagName = null;
    boolean done = false;
    int eventType = 0;
    
    // Get the time layout
    forecast.conditionIcon.timeLayout = parser.getAttributeValue(null, LAYOUT_TYPE);
    
    while(eventType != XmlPullParser.END_DOCUMENT && !done && !abort) {
      // Do the parse at the start so that parser is in correct location on exit
      eventType = parser.next();
      
      switch(eventType) {
      case XmlPullParser.START_TAG:
        tagName = parser.getName();
        // Get all the icons for the days
        if(tagName.equalsIgnoreCase(ICON)) {
          forecast.conditionIcon.data.add(parser.nextText());
        }
        
        break;
        
      case XmlPullParser.END_TAG:
        tagName = parser.getName();
        if(tagName.equalsIgnoreCase(ICON_ROOT)) {
          // end the loop when the closing root is reached
          done = true;
        }
        break;
      }
    }
    
    forecast.conditionIcon.print("Icon");
    
    return parser;
  }
  
  private XmlPullParser parseForecast(XmlPullParser parser) throws XmlPullParserException, IOException {
    String tagName = null;
    boolean done = false;
    int eventType = 0;
    
    // Get the time layout
    forecast.forecastText.timeLayout = parser.getAttributeValue(null, LAYOUT_TYPE);
    
    while(eventType != XmlPullParser.END_DOCUMENT && !done && !abort) {
      // Do the parse at the start so that parser is in correct location on exit
      eventType = parser.next();
      
      switch(eventType) {
      case XmlPullParser.START_TAG:
        tagName = parser.getName();
        // Get all the weather forecasts
        if(tagName.equalsIgnoreCase(FORECAST_TEXT)) {
          forecast.forecastText.data.add(parser.nextText());
        }
        
        break;
        
      case XmlPullParser.END_TAG:
        tagName = parser.getName();
        if(tagName.equalsIgnoreCase(FORECAST_ROOT)) {
          // end the loop when the closing root is reached
          done = true;
        }
        break;
      }
    }
    
    forecast.forecastText.print("Forecast");
    
    return parser;
  }
}




Java Source Code List

com.SyntheticCode.BlueSkyWeather.AboutActivity.java
com.SyntheticCode.BlueSkyWeather.BlueSkyActivity.java
com.SyntheticCode.BlueSkyWeather.CityData.java
com.SyntheticCode.BlueSkyWeather.ForecastData.java
com.SyntheticCode.BlueSkyWeather.ForecastParserTask.java
com.SyntheticCode.BlueSkyWeather.ForecastShortView.java
com.SyntheticCode.BlueSkyWeather.SearchResultActivity.java
com.SyntheticCode.BlueSkyWeather.SettingsActivity.java
com.SyntheticCode.BlueSkyWeather.StationList.java
com.SyntheticCode.BlueSkyWeather.StationParserTask.java
com.SyntheticCode.BlueSkyWeather.UiObjects.java
com.SyntheticCode.BlueSkyWeather.WeatherData.java
com.SyntheticCode.BlueSkyWeather.WeatherParserTask.java
com.SyntheticCode.BlueSkyWeather.WeatherStation.java
com.SyntheticCode.BlueSkyWeather.parsers.BaseFeedParser.java
com.SyntheticCode.BlueSkyWeather.parsers.ForecastParser.java
com.SyntheticCode.BlueSkyWeather.parsers.GeoLookupParser.java
com.SyntheticCode.BlueSkyWeather.parsers.StationPullParser.java