/*
* Copyright 2011 Adi Sayoga.
*
* 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 com.adisayoga.earthquake.models;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.AlarmManager;
import android.net.Uri;
import android.util.Log;
import com.adisayoga.earthquake.dto.EarthquakeDTO;
import com.adisayoga.earthquake.utils.TimeUtils;
/**
* Class untuk komunikasi data dengan USGS.
*
* @author Adi Sayoga
*/
public class UsgsSource {
private static final String TAG = "UsgsSource";
public static final String FEED = "http://earthquake.usgs.gov/earthquakes/catalogs/";
public static final String DETAIL = "http://earthquake.usgs.gov/earthquakes/recenteqsww/Quakes/";
public static final String GLOBE = "http://earthquake.usgs.gov/images/globes/";
/*public static final String FEED = "http://10.0.2.2/earthquake/";
public static final String DETAIL = "http://10.0.2.2/earthquake/details/";
public static final String GLOBE = "http://10.0.2.2/earthquake/globes/";*/
private static final Pattern PATTERN = Pattern.compile(
// src____ eqid___ ver____ datetime________ lat____ lon____ mag_____
"([^,]+),([^,]+),([^,]+),\"([^\"]+) UTC\",([^,]+),([^,]+),([^,]+),"
// depth__ nst________ region______
+ "([^,]+),\\s?([^,]+),\"([^\"]+)\"");
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("EEEE, MMMM d, yyyy HH:mm:ss", Locale.US);
private UsgsSource() {
}
/**
* Membaca data feed dari usgs.
*
* @param lastUpdate Terakhir kali data diambil
* @param minMagnitude Magnitudo minimal
* @return ArrayList dari data gempa
* @throws IOException Jika tidak dapat connect ke server
*/
public static List<EarthquakeDTO> read(long lastUpdate, float minMagnitude)
throws IOException {
Log.i(TAG, "Mendapatkan data dari server...");
BufferedReader reader = null;
List<EarthquakeDTO> quakes = new ArrayList<EarthquakeDTO>();
long interval = System.currentTimeMillis() - lastUpdate;
try {
URL url = getUrl(minMagnitude, interval);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(30 * 1000); // 30 detik
connection.setReadTimeout(30 * 1000); // 30 detik
if (connection.getResponseCode() != 200) {
// Koneksi gagal
Log.e(TAG, "Koneksi gagal, response code: " + connection
.getResponseCode());
return null;
}
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),
"ISO-8859-1"), 8192);
String line;
while ((line = reader.readLine()) != null) {
try {
EarthquakeDTO quake = getQuake(line);
if (quake != null) quakes.add(quake);
} catch (Exception e) {
Log.e(TAG, "Error parse data dari baris: " + line, e);
}
}
Log.d(TAG, "Selesai mengambil data: " + quakes.size() + " items");
return quakes;
} catch (IOException e) {
Log.e(TAG, "Gagal mendapatkan data dari server: " + e.getMessage());
throw e;
} finally {
try { if (reader != null) reader.close(); } catch(IOException e) {}
}
}
/**
* Mendapatkan url feed USGS berdasarkan minimal magnitudo dan interval refresh.
*
* @param minMagnitude Minimal magnitudo
* @param interval Interval refresh
* @return Url feed USGS
* @throws MalformedURLException
*/
private static URL getUrl(float minMagnitude, long interval)
throws MalformedURLException {
String filename;
if (interval <= AlarmManager.INTERVAL_HOUR) { // 1 jam kurang
if (minMagnitude < 1) {
filename = "eqs1hour-M0.txt";
} else {
filename = "eqs1hour-M1.txt";
}
} else if (interval <= AlarmManager.INTERVAL_DAY) { // 1 hari kurang
if (minMagnitude < 1) {
filename = "eqs1day-M0.txt";
} else if (minMagnitude < 2.5) {
filename = "eqs1day-M1.txt";
} else {
filename = "eqs1day-M2.5.txt";
}
} else { // 1 hari keatas
if (minMagnitude < 5) {
filename = "eqs7day-M2.5.txt";
} else if (minMagnitude < 7) {
filename = "eqs7day-M5.txt";
} else {
filename = "eqs7day-M7.txt";
}
}
URL url = new URL(FEED + filename);
Log.d(TAG, "Magnitude=" + minMagnitude + " interval=" + interval
+ ", url dipilih: " + url.toString());
return url;
}
/**
* Parse data baris string ke objek EarthquakeDTO.
*
* @param line Baris data sumber
* @param lastUpdate Terakhir kali diupdate
* @return Objek EarthquakeDTO
* @throws NumberFormatException
* @throws ParseException
*/
private static EarthquakeDTO getQuake(String line)
throws NumberFormatException, ParseException {
Matcher matcher = PATTERN.matcher(line);
if (!matcher.matches()) return null;
String source = matcher.group(1);
String eqid = matcher.group(2);
String version = matcher.group(3);
double latitude = Double.parseDouble(matcher.group(5));
double longitude = Double.parseDouble(matcher.group(6));
long time = TimeUtils.parseDate(matcher.group(4), DATE_FORMAT).getTime();
float magnitude = Float.parseFloat(matcher.group(7));
float depth = Float.parseFloat(matcher.group(8)) * 1000;
int nst = Integer.parseInt(matcher.group(9));
String region = matcher.group(10);
return new EarthquakeDTO(0, source, eqid, version, time, latitude, longitude,
magnitude, depth, nst, region);
}
/**
* Mendapatkan alamat URL untuk gambar globe.
*
* @param quake Data gempa
* @return URL globe atau null jika terdapat kesalahan
*/
public static URL getGlobeURL(EarthquakeDTO quake) {
// Bulatkan (step 5)
int latitude = (int) (Math.round(quake.latitude / 5) * 5);
int longitude = (int) (Math.round(quake.longitude / 5) * 5);
String imageName = latitude + "_" + longitude + ".jpg";
try {
URL url = new URL(UsgsSource.GLOBE + imageName);
Log.d(TAG, "getImageUri: latitude=" + quake.latitude + ", longitude="
+ quake.longitude + ", image=" + url.toString());
return url;
} catch (MalformedURLException e) {
Log.e(TAG, "Error generate url, " + e.getMessage());
return null;
}
}
/**
* Mendapatkan alamat uri detail gempa pada USGS.
*
* @param quake Data gempa
* @return Uri detail gempa pada USGS
*/
public static Uri getExternalUri(EarthquakeDTO quake) {
return Uri.parse(UsgsSource.DETAIL + quake.source + quake.eqid + ".php");
}
}