com.none.tom.simplerssreader.utils.SharedPrefUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.none.tom.simplerssreader.utils.SharedPrefUtils.java

Source

// Copyright (c) 2017-2018, Tom Geiselmann
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
// and associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY,WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package com.none.tom.simplerssreader.utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import com.google.common.collect.LinkedListMultimap;
import com.none.tom.simplerssreader.R;
import com.none.tom.simplerssreader.opml.Outline;
import com.none.tom.simplerssreader.opml.OutlineGroup;

import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import static com.none.tom.simplerssreader.utils.Constants.KEY_SHARED_PREFERENCES;

public class SharedPrefUtils {
    private static final String KEY_SUBSCRIPTIONS = "key_subscriptions";
    private static final String KEY_SUBSCRIPTION_CATEGORIES = "key_subscription_categories";
    private static final String KEY_SUBSCRIPTION_URLS = "key_subscription_urls";
    private static final String KEY_SUBSCRIPTION_TITLES = "key_subscription_titles";
    private static final String KEY_SUBSCRIPTION_IDS = "key_subscription_ids";
    private static final String KEY_CURRENT_FEED_POSITION = "key_current_feed_position";
    private static final String KEY_PREVIOUS_FEED_POSITION = "key_previous_feed__position";

    private static LinkedListMultimap<String, String> sSubscriptions;
    private static List<List<Object>> sSubscriptionList;

    private static SharedPreferences sSharedPreferences;

    @SuppressWarnings("unchecked")
    public static <T> T get(final Context context, final String key, final Class<T> clazz) {
        if (clazz.equals(String.class)) {
            return (T) getSharedPreferences(context).getString(key, null);
        }
        return (T) (Integer) getSharedPreferences(context).getInt(key, 0);
    }

    public static <T> void put(final Context context, final String key, @Nullable final T value) {
        final SharedPreferences.Editor preferences = getSharedPreferences(context).edit();

        if (value == null || value instanceof String) {
            preferences.putString(key, (String) value);
        } else {
            preferences.putInt(key, (Integer) value);
        }

        preferences.apply();
    }

    private static SharedPreferences getSharedPreferences(final Context context) {
        if (sSharedPreferences == null) {
            sSharedPreferences = context.getSharedPreferences(KEY_SHARED_PREFERENCES, Context.MODE_PRIVATE);
        }

        return sSharedPreferences;
    }

    private static LinkedListMultimap<String, String> getSubscriptions(final Context context) {
        if (sSubscriptions == null) {
            sSubscriptions = LinkedListMultimap.create();

            final String subscriptions = get(context, KEY_SUBSCRIPTIONS, String.class);

            if (!TextUtils.isEmpty(subscriptions)) {
                try {
                    final JSONObject JSON = new JSONObject(subscriptions);
                    final JSONArray titlesJSON = JSON.getJSONArray(KEY_SUBSCRIPTION_TITLES);
                    final JSONArray categoriesJSON = JSON.getJSONArray(KEY_SUBSCRIPTION_CATEGORIES);
                    final JSONArray idsJSON = JSON.getJSONArray(KEY_SUBSCRIPTION_IDS);
                    final JSONArray urlsJSON = JSON.getJSONArray(KEY_SUBSCRIPTION_URLS);

                    for (int i = 0; i < titlesJSON.length(); i++) {
                        final String title = titlesJSON.getString(i);

                        sSubscriptions.put(title, categoriesJSON.getString(i));
                        sSubscriptions.put(title, idsJSON.getString(i));
                        sSubscriptions.put(title, urlsJSON.getString(i));
                    }
                } catch (final JSONException e) {
                    LogUtils.logError(e);
                }
            }
        }

        return sSubscriptions;
    }

    public static String getSubscriptionTitleAt(final Context context, final int position) {
        final List<String> titles = new ArrayList<>(getSubscriptions(context).asMap().keySet());

        if (titles.size() > position) {
            return titles.get(position);
        }

        return null;
    }

    public static String getSubscriptionIdAt(final Context context, final int position) {
        final String title = getSubscriptionTitleAt(context, position);

        if (!TextUtils.isEmpty(title)) {
            return getSubscriptions(context).get(title).get(1);
        }

        return null;
    }

    public static String getSubscriptionUrlAt(final Context context, final int position) {
        final String title = getSubscriptionTitleAt(context, position);

        if (!TextUtils.isEmpty(title)) {
            return getSubscriptions(context).get(title).get(2);
        }

        return null;
    }

    public static List<String> getSubscriptionTitlesFor(final Context context, final List<Integer> positions) {
        final List<String> titles = new ArrayList<>(getSubscriptions(context).asMap().keySet());
        final List<String> result = new ArrayList<>(positions.size());

        for (final int position : positions) {
            result.add(titles.get(position));
        }

        return result;
    }

    public static List<List<Object>> getSubscriptionsFor(final Context context, final String newCategory) {
        if (sSubscriptionList == null) {
            final LinkedListMultimap<String, String> subscriptions = getSubscriptions(context);
            final boolean queryEmpty = TextUtils.isEmpty(newCategory);

            sSubscriptionList = new ArrayList<>(subscriptions.size());

            int i = 0;

            for (final String title : subscriptions.asMap().keySet()) {
                final String category = subscriptions.get(title).get(0);

                if (queryEmpty || newCategory.equals(category)) {
                    if (queryEmpty) {
                        sSubscriptionList.add(Arrays.<Object>asList(title, category));
                    } else {
                        sSubscriptionList.add(Arrays.<Object>asList(title, category, i));
                    }
                }

                i++;
            }
        }

        return sSubscriptionList;
    }

    static List<Object> getSubscriptionsAsOutlines(final Context context, final boolean retainCategories) {
        final LinkedListMultimap<String, String> subscriptions = getSubscriptions(context);

        final List<Object> outlines = new ArrayList<>(subscriptions.size());
        final LinkedListMultimap<String, Outline> outlineGroups = LinkedListMultimap.create();

        for (final String title : subscriptions.asMap().keySet()) {
            final String category = subscriptions.get(title).get(0);
            final String xmlUrl = subscriptions.get(title).get(2);

            final Outline outline = new Outline.Builder().setText(title).setTitle(title).setXmlUrl(xmlUrl).build();

            if (retainCategories) {
                outlineGroups.put(category, outline);
            } else {
                outlines.add(outline);
            }
        }

        if (retainCategories) {
            for (final String category : outlineGroups.asMap().keySet()) {
                outlines.add(new OutlineGroup.Builder().setText(category).setTitle(category)
                        .addSubOutlines(outlineGroups.get(category)).build());
            }
        }

        return outlines;
    }

    public static String[] getSubscriptionCategories(final Context context, final boolean edit) {
        final LinkedListMultimap<String, String> subscriptions = getSubscriptions(context);
        final Set<String> categories = new TreeSet<>();

        if (!edit) {
            categories.add(context.getString(R.string.all_categories));
        } else {
            categories.add(context.getString(R.string.clear_category));
        }

        for (final String title : subscriptions.asMap().keySet()) {
            categories.add(subscriptions.get(title).get(0));
        }

        return categories.toArray(new String[categories.size()]);
    }

    private static int getSubscriptionPositionAfterEdit(final Context context, final String newTitle) {
        int i = 0;

        for (final String title : getSubscriptions(context).asMap().keySet()) {
            if (title.equals(newTitle)) {
                break;
            }
            i++;
        }
        return i;
    }

    public static int getSubscriptionsCnt(final Context context) {
        return getSubscriptions(context).asMap().size();
    }

    public static int addSubscription(final Context context, final String title, final String category,
            final String url) {
        final LinkedListMultimap<String, String> subscriptions = getSubscriptions(context);
        final String currentTitle = getCurrentFeedTitle(context);

        subscriptions.putAll(title, Arrays.asList(category, "", url));

        saveSubscriptions(context, subscriptions);

        return updateCurrentFeedPosition(context, currentTitle);
    }

    public static void addSubscriptions(final Context context, final List outlines) {
        final LinkedListMultimap<String, String> subscriptions = getSubscriptions(context);

        for (final Object outline : outlines) {
            if (outline instanceof Outline) {
                final String text = ((Outline) outline).getText();
                final String xmlUrl = ((Outline) outline).getXmlUrl();
                final String category = context.getString(R.string.uncategorized);

                if (!TextUtils.isEmpty(xmlUrl) && !TextUtils.isEmpty(text) && !subscriptions.containsKey(text)) {
                    subscriptions.putAll(text.trim(), Arrays.asList(category, "", xmlUrl));
                }
            } else {
                for (final Outline subOutline : ((OutlineGroup) outline).getOutlines()) {
                    final String text = subOutline.getText();
                    final String xmlUrl = subOutline.getXmlUrl();
                    final String category = ((OutlineGroup) outline).getText();

                    if (!TextUtils.isEmpty(xmlUrl) && !TextUtils.isEmpty(text)
                            && !subscriptions.containsKey(text)) {
                        subscriptions.putAll(text.trim(), Arrays.asList(category, "", xmlUrl));
                    }
                }
            }
        }

        final String currentTitle = getCurrentFeedTitle(context);

        saveSubscriptions(context, subscriptions);

        updateCurrentFeedPosition(context, currentTitle);
    }

    private static void saveSubscriptions(final Context context,
            final LinkedListMultimap<String, String> subscriptions) {
        if (subscriptions != null) {
            final JSONObject JSON = new JSONObject();
            final JSONArray titlesJSON = new JSONArray();
            final JSONArray categoriesJSON = new JSONArray();
            final JSONArray idsJSON = new JSONArray();
            final JSONArray urlsJSON = new JSONArray();

            final List<String> titles = new ArrayList<>(subscriptions.asMap().keySet());

            Collections.sort(titles);

            for (final String title : titles) {
                final Iterator<String> iter = subscriptions.get(title).iterator();

                titlesJSON.put(title);
                categoriesJSON.put(iter.next());
                idsJSON.put(iter.next());
                urlsJSON.put(iter.next());
            }

            try {
                JSON.put(KEY_SUBSCRIPTION_TITLES, titlesJSON);
                JSON.put(KEY_SUBSCRIPTION_CATEGORIES, categoriesJSON);
                JSON.put(KEY_SUBSCRIPTION_IDS, idsJSON);
                JSON.put(KEY_SUBSCRIPTION_URLS, urlsJSON);

                put(context, KEY_SUBSCRIPTIONS, JSON.toString());
            } catch (final JSONException e) {
                LogUtils.logError(e);
            }
        } else {
            put(context, KEY_SUBSCRIPTIONS, null);
        }

        sSubscriptions = null;
        sSubscriptionList = null;
    }

    @SuppressWarnings("ConstantConditions")
    public static void updateSubscriptionUrl(final Context context, final String feedUrl) {
        final LinkedListMultimap<String, String> subscriptions = getSubscriptions(context);

        final int position = getCurrentFeedPosition(context);
        final String title = getSubscriptionTitleAt(context, position);

        final List<String> values = subscriptions.get(title);

        values.set(2, feedUrl);
        subscriptions.replaceValues(title, values);

        saveSubscriptions(context, subscriptions);
    }

    @SuppressWarnings("ConstantConditions")
    public static void updateSubscriptionIdAt(final Context context, final String id, final int position) {
        final LinkedListMultimap<String, String> subscriptions = getSubscriptions(context);

        final String title = getSubscriptionTitleAt(context, position);
        final List<String> values = subscriptions.get(title);

        values.set(1, id);
        subscriptions.replaceValues(title, values);

        saveSubscriptions(context, subscriptions);
    }

    @SuppressWarnings("ConstantConditions")
    public static void updateSubscriptionCategoryTitleAt(final Context context, final String category,
            final String newTitle, final int position) {
        final LinkedListMultimap<String, String> subscriptions = getSubscriptions(context);
        final String title = getSubscriptionTitleAt(context, position);

        final List<String> values = subscriptions.get(title);
        final boolean newCategory = !values.get(0).equals(category);

        if (newCategory || !newTitle.equals(title)) {
            if (newCategory) {
                final List<String> newValues = new ArrayList<>(subscriptions.removeAll(title));
                newValues.set(0, category);

                subscriptions.putAll(newTitle, newValues);
            } else {
                subscriptions.putAll(newTitle, subscriptions.removeAll(title));
            }

            saveSubscriptions(context, subscriptions);

            updateCurrentFeedPosition(context, newTitle);
        }
    }

    public static boolean unsubscribe(final Context context, final List<String> titles) {
        final LinkedListMultimap<String, String> subscriptions = getSubscriptions(context);

        if (subscriptions.asMap().size() < 2) {
            saveSubscriptions(context, null);

            putCurrentFeedPosition(context, 0);
            putPreviousFeedPosition(context, 0);

            return false;
        }

        final String currentTitle = getCurrentFeedTitle(context);

        for (final String title : titles) {
            subscriptions.removeAll(title);
        }

        if (subscriptions.isEmpty()) {
            saveSubscriptions(context, null);

            putCurrentFeedPosition(context, 0);
            putPreviousFeedPosition(context, 0);

            return false;
        }

        saveSubscriptions(context, subscriptions);

        if (subscriptions.containsKey(currentTitle)) {
            updateCurrentFeedPosition(context, currentTitle);

            return false;
        }

        return true;
    }

    public static void invalidateSubscriptionList() {
        sSubscriptionList = null;
    }

    public static boolean isSubscriptionsEmpty(final Context context) {
        return getSubscriptions(context).isEmpty();
    }

    public static SearchResults getSearchResultsFor(final Context context, final String query, final int position) {
        final List<Integer> positions = new ArrayList<>();
        final List<LinkedHashMap<Integer, Integer>> indices = new ArrayList<>();

        int i = 0;

        for (final String title : getSubscriptions(context).asMap().keySet()) {
            if (StringUtils.containsIgnoreCase(title, query)) {
                indices.add(SearchUtils.getIndicesForQuery(title, query));
                positions.add(i);
            }

            i++;
        }

        return new SearchResults(position, positions, indices);
    }

    public static int getCurrentFeedPosition(final Context context) {
        return get(context, KEY_CURRENT_FEED_POSITION, Integer.class);
    }

    public static void putCurrentFeedPosition(final Context context, final int position) {
        putPreviousFeedPosition(context, getCurrentFeedPosition(context));
        put(context, KEY_CURRENT_FEED_POSITION, position);
    }

    private static void putPreviousFeedPosition(final Context context, final int position) {
        put(context, KEY_PREVIOUS_FEED_POSITION, position);
    }

    public static int getPreviousFeedPosition(final Context context) {
        return get(context, KEY_PREVIOUS_FEED_POSITION, Integer.class);
    }

    private static int updateCurrentFeedPosition(final Context context, final String title) {
        if (!TextUtils.isEmpty(title)) {
            final int position = getSubscriptionPositionAfterEdit(context, title);
            putCurrentFeedPosition(context, position);

            return position;
        }

        return 0;
    }

    public static String getCurrentFeedUrl(final Context context) {
        return getSubscriptionUrlAt(context, getCurrentFeedPosition(context));
    }

    public static String getCurrentFeedTitle(final Context context) {
        return getSubscriptionTitleAt(context, getCurrentFeedPosition(context));
    }
}