/* * Copyright (c) 2015 PocketHub * * 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.github.pockethub.android.ui.repo; import android.content.Context; import android.os.AsyncTask; import com.meisolsson.githubsdk.model.Repository; import com.meisolsson.githubsdk.model.User; import com.github.pockethub.android.RequestReader; import com.github.pockethub.android.RequestWriter; import java.io.File; import java.io.Serializable; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedHashSet; import static java.lang.String.CASE_INSENSITIVE_ORDER; /** * Model class for the repositories recently selected under an organization */ public class RecentRepositories implements Comparator<Repository>, Serializable { /** * Number of repositories retained per organization */ public static final int MAX_SIZE = 5; private static final long serialVersionUID = 580345177644233739L; private static final int VERSION = 2; private static File getFile(final Context context, final User organization) { return new File(context.getFilesDir(), "recent-repos-" + organization.id() + ".ser"); } private LinkedHashSet<Long> ids; private final File file; private int id; /** * Create a recent repositories cache for the given organization * * @param context * @param organization */ public RecentRepositories(final Context context, final User organization) { file = getFile(context, organization); id = organization.id(); } private void load() { LinkedHashSet<Long> loaded = new RequestReader(file, VERSION).read(); if (loaded == null) { loaded = new LinkedHashSet<>(); } ids = loaded; trim(); } private void trim() { Iterator<Long> iterator = ids.iterator(); while (iterator.hasNext() && ids.size() > MAX_SIZE) { iterator.next(); iterator.remove(); } } /** * Add repository to recent list * * @param repo * @return this recent list */ public RecentRepositories add(final Repository repo) { return repo != null ? add(repo.id()) : this; } /** * Add id to recent list * * @param id * @return this recent list */ public RecentRepositories add(final long id) { if (ids == null) { load(); } ids.remove(id); ids.add(id); trim(); return this; } /** * Remove repository from recent list * * @param repo * @return this recent list */ public RecentRepositories remove(final Repository repo) { return repo != null ? remove(repo.id()) : this; } /** * Remove id from recent list * * @param id * @return this recent list */ public RecentRepositories remove(final long id) { if (ids == null) { load(); } ids.remove(id); return this; } /** * Persist recent list asynchronously on a background thread * * @return this recent list */ public RecentRepositories saveAsync() { if (ids != null) { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { save(); return null; } }.execute(); } return this; } /** * Persist recent list * * @return this recent list */ public RecentRepositories save() { final LinkedHashSet<Long> save = ids; if (save != null) { new RequestWriter(file, VERSION).write(save); } return this; } /** * Is the given repository in the recent list? * * @param repository * @return true if in recent list, false otherwise */ public boolean contains(Repository repository) { return repository != null && contains(repository.id()); } /** * Is the given repository id in the recent list * * @param id * @return true if in recent list, false otherwise */ public boolean contains(long id) { if (ids == null) { load(); } return ids.contains(id); } @Override public int compare(final Repository lhs, final Repository rhs) { final boolean lRecent = contains(lhs); final boolean rRecent = contains(rhs); if (lRecent && !rRecent) { return -1; } if (!lRecent && rRecent) { return 1; } final int order = CASE_INSENSITIVE_ORDER.compare(lhs.name(), rhs.name()); if (order == 0) { if (id == lhs.owner().id()) { return -1; } else if (id == rhs.owner().id()) { return 1; } else { return CASE_INSENSITIVE_ORDER.compare( lhs.owner().login(), rhs.owner().login()); } } else { return order; } } }