/* * 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.persistence; import android.accounts.Account; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import com.github.pockethub.android.core.PageIterator; import com.meisolsson.githubsdk.core.ServiceGenerator; import com.meisolsson.githubsdk.model.Page; import com.meisolsson.githubsdk.model.Permissions; import com.meisolsson.githubsdk.model.Repository; import com.meisolsson.githubsdk.model.User; import com.meisolsson.githubsdk.service.activity.WatchingService; import com.meisolsson.githubsdk.service.repositories.RepositoryService; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.assistedinject.Assisted; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; import retrofit2.Response; /** * Cache of repositories under a given organization */ public class OrganizationRepositories implements PersistableResource<Repository> { /** * Creation factory */ public interface Factory { /** * Get repositories under given organization * * @param org * @return repositories */ OrganizationRepositories under(User org); } private final User org; private final Context context; private final Provider<Account> accountProvider; /** * Create repositories cache for a given organization * * @param orgs * @param context * @param accountProvider */ @Inject public OrganizationRepositories(@Assisted User orgs, Context context, Provider<Account> accountProvider) { this.org = orgs; this.context = context; this.accountProvider = accountProvider; } @Override public Cursor getCursor(SQLiteDatabase readableDatabase) { SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); builder.setTables("repos JOIN users ON (repos.ownerId = users.id)"); return builder.query(readableDatabase, new String[] { "repos.repoId", "repos.name", "users.id", "users.name", "users.avatarurl", "repos.private", "repos.fork", "repos.description", "repos.forks", "repos.watchers", "repos.language", "repos.hasIssues", "repos.mirrorUrl", "repos.permissions_admin", "repos.permissions_pull", "repos.permissions_push" }, "repos.orgId=?", new String[] { Integer.toString(org.id()) }, null, null, null); } @Override public Repository loadFrom(Cursor cursor) { User owner = User.builder() .login(cursor.getString(3)) .id(cursor.getInt(2)) .avatarUrl(cursor.getString(4)) .build(); Permissions permissions = Permissions.builder() .admin(cursor.getInt(13) == 1) .push(cursor.getInt(14) == 1) .pull(cursor.getInt(15) == 1) .build(); return Repository.builder() .owner(owner) .name(cursor.getString(1)) .id(cursor.getLong(0)) .isPrivate(cursor.getInt(5) == 1) .isFork(cursor.getInt(6) == 1) .description(cursor.getString(7)) .forksCount(cursor.getInt(8)) .watchersCount(cursor.getInt(9)) .language(cursor.getString(10)) .hasIssues(cursor.getInt(11) == 1) .mirrorUrl(cursor.getString(12)) .permissions(permissions) .build(); } @Override public void store(SQLiteDatabase db, List<Repository> repos) { db.delete("repos", "orgId=?", new String[] { Integer.toString(org.id()) }); if (repos.isEmpty()) { return; } ContentValues values = new ContentValues(12); for (Repository repo : repos) { values.clear(); User owner = repo.owner(); values.put("repoId", repo.id()); values.put("name", repo.name()); values.put("orgId", org.id()); values.put("ownerId", owner.id()); values.put("private", repo.isPrivate() ? 1 : 0); values.put("fork", repo.isFork() ? 1 : 0); values.put("description", repo.description()); values.put("forks", repo.forksCount()); values.put("watchers", repo.watchersCount()); values.put("language", repo.language()); values.put("hasIssues", repo.hasIssues() ? 1 : 0); values.put("mirrorUrl", repo.mirrorUrl()); values.put("permissions_admin", repo.permissions().admin() ? 1 : 0); values.put("permissions_pull", repo.permissions().pull() ? 1 : 0); values.put("permissions_push", repo.permissions().push() ? 1 : 0); db.replace("repos", null, values); values.clear(); values.put("id", owner.id()); values.put("name", owner.login()); values.put("avatarurl", owner.avatarUrl()); db.replace("users", null, values); } } @Override public List<Repository> request() throws IOException { if (isAuthenticatedUser()) { Set<Repository> all = new TreeSet<>((repo1, repo2) -> { final long id1 = repo1.id(); final long id2 = repo2.id(); if (id1 > id2) { return 1; } if (id1 < id2) { return -1; } return 0; }); all.addAll(getAllItems(page -> ServiceGenerator.createService(context, RepositoryService.class) .getUserRepositories(page))); all.addAll(getAllItems(page -> ServiceGenerator.createService(context, WatchingService.class) .getWatchedRepositories(page))); return new ArrayList<>(all); } else { return getAllItems(page -> ServiceGenerator.createService(context, RepositoryService.class) .getOrganizationRepositories(org.login(), page)); } } private List<Repository> getAllItems(PageIterator.GitHubRequest<Response<Page<Repository>>> request) { List<Repository> repos = new ArrayList<>(); int current = 1; int last = -1; while(current != last) { Page<Repository> page = request.execute(current).blockingGet().body(); repos.addAll(page.items()); last = page.last() != null ? page.last() : -1; current = page.next() != null ? page.next() : -1; } return repos; } private boolean isAuthenticatedUser() { return org.login().equals(accountProvider.get().name); } @Override public String toString() { return getClass().getSimpleName() + '[' + org.login() + ']'; } }