org.voidsink.anewjkuapp.mensa.JSONMenuLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.voidsink.anewjkuapp.mensa.JSONMenuLoader.java

Source

/*
 *      ____.____  __.____ ___     _____
 *     |    |    |/ _|    |   \   /  _  \ ______ ______
 *     |    |      < |    |   /  /  /_\  \\____ \\____ \
 * /\__|    |    |  \|    |  /  /    |    \  |_> >  |_> >
 * \________|____|__ \______/   \____|__  /   __/|   __/
 *                  \/                  \/|__|   |__|
 *
 * 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;
    }
}