Java tutorial
/* * ____.____ __.____ ___ _____ * | | |/ _| | \ / _ \ ______ ______ * | | < | | / / /_\ \\____ \\____ \ * /\__| | | \| | / / | \ |_> > |_> > * \________|____|__ \______/ \____|__ / __/| __/ * \/ \/|__| |__| * * Copyright (c) 2014-2015 Paul "Marunjar" Pretsch * * 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 3 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, see <http://www.gnu.org/licenses/> * */ package org.voidsink.anewjkuapp.mensa; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.support.v7.preference.PreferenceManager; import android.text.format.DateUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.voidsink.anewjkuapp.R; import org.voidsink.anewjkuapp.analytics.Analytics; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; import java.net.HttpURLConnection; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; public abstract class JSONMenuLoader implements MenuLoader { protected abstract String getUrl(); private static final String PREF_DATA_PREFIX = "MENSA_DATA_"; private static final String PREF_DATE_PREFIX = "MENSA_DATE_"; protected abstract String getCacheKey(); protected abstract String getMensaKey(); private String getData(Context context) { String result = null; String cacheDateKey = PREF_DATE_PREFIX + getCacheKey(); String cacheDataKey = PREF_DATA_PREFIX + getCacheKey(); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); if (sp.getLong(cacheDateKey, 0) > (System.currentTimeMillis() - 6 * DateUtils.HOUR_IN_MILLIS)) { result = sp.getString(cacheDataKey, null); } if (result == null) { try { URL url = new URL(getUrl()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(15000); Writer writer = new StringWriter(); char[] buffer = new char[1024]; Reader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); int n; while ((n = reader.read(buffer)) != -1) { writer.write(buffer, 0, n); } result = writer.toString(); conn.disconnect(); Editor editor = sp.edit(); editor.putString(cacheDataKey, result); editor.putLong(cacheDateKey, System.currentTimeMillis()); editor.apply(); } catch (Exception e) { Analytics.sendException(context, e, false); result = sp.getString(cacheDataKey, null); } } return result; } private String getLocation(Context c, int nr) { switch (nr) { case 1: return c.getString(R.string.mensa_title_classic); case 2: return c.getString(R.string.mensa_title_choice); case 3: return c.getString(R.string.mensa_title_khg); case 4: return c.getString(R.string.mensa_title_raab); default: return c.getString(R.string.mensa_title_unknown); } } public IMensa getMensa(Context context) { Mensa mensa = null; try { String data = getData(context); if (data != null) { JSONObject jsonData = new JSONObject(data); if (jsonData.getString("success").equals("true")) { JSONObject jsonMensa = jsonData.getJSONObject("result"); mensa = new Mensa(getMensaKey(), getLocation(context, Integer.parseInt(jsonMensa.getString("location")))); JSONArray jsonDays = jsonMensa.getJSONArray("offers"); for (int i = 0; i < jsonDays.length(); i++) { JSONObject jsonDay = jsonDays.getJSONObject(i); MensaDay day = new MensaDay(jsonDay); onNewDay(day); mensa.addDay(day); JSONArray jsonMenus = jsonDay.getJSONArray("menus"); checkName(jsonMenus); normalize(context, jsonMenus); for (int j = 0; j < jsonMenus.length(); j++) { day.addMenu(new MensaMenu(jsonMenus.getJSONObject(j))); } } } } } catch (Exception e) { Analytics.sendException(context, e, false); return null; } return mensa; } private void checkName(JSONArray jsonMenus) throws JSONException { if (getNameFromMeal()) { for (int i = 0; i < jsonMenus.length(); i++) { JSONObject jsonMenu = jsonMenus.getJSONObject(i); String meal = jsonMenu.getString("meal"); String name = ""; // get name from meal, separated by : int index = meal.indexOf(":"); if (index >= 0) { name = meal.substring(0, index).trim(); if (index < meal.length()) { meal = meal.substring(index + 1, meal.length()).trim(); } } jsonMenu.put("name", name); jsonMenu.put("meal", meal); } } } //push every followup-element one position later private void insert(JSONArray a, Object o, int index) throws JSONException { if (index >= a.length() || index < 0) { //just for some cornercases a.put(o); } else { Object tmp = a.get(index); a.put(index, o); //recursion ftw insert(a, tmp, index + 1); } } private void normalize(Context c, JSONArray jsonDays) { final Pattern pricePattern = Pattern.compile("(? ?)\\d[\\,\\.]\\d{2}( ??)"); int i = 0; while (i < jsonDays.length()) { try { JSONObject jsonDay = jsonDays.getJSONObject(i); String meal = jsonDay.getString("meal").trim(); Matcher priceMatcher = pricePattern.matcher(meal); if (priceMatcher.find()) { // get rest of meal and insert for processing as next String nextMeal = meal.substring(priceMatcher.end()).trim(); if (Pattern.compile("\\w+").matcher(nextMeal).find()) { JSONObject clone = new JSONObject(jsonDay.toString()); clone.put("meal", nextMeal); insert(jsonDays, clone, i + 1); } // insert meal jsonDay.put("meal", meal.substring(0, priceMatcher.start()).trim()); jsonDay.put("price", normalizePrice(meal.substring(priceMatcher.start(), priceMatcher.end()))); } } catch (JSONException e) { Analytics.sendException(c, e, false); } i++; } } private String normalizePrice(String price) { String result = price.trim().replaceAll("[ ]", ""); try { String[] parts = result.split("[\\,\\.]"); if (parts.length == 2 && parts[1].length() == 2) { result = parts[0] + parts[1]; } else { result = ""; } } catch (Exception e) { result = ""; } return result; } protected void onNewDay(MensaDay day) { } protected boolean getNameFromMeal() { return false; } }