mirror of https://github.com/kurisufriend/Clover
parent
a91cc5155c
commit
7ef0243922
@ -0,0 +1,189 @@ |
|||||||
|
/* |
||||||
|
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||||
|
* Copyright (C) 2014 Floens |
||||||
|
* |
||||||
|
* 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.floens.chan.core.repository; |
||||||
|
|
||||||
|
import android.util.Pair; |
||||||
|
|
||||||
|
import org.floens.chan.core.database.DatabaseBoardManager; |
||||||
|
import org.floens.chan.core.database.DatabaseManager; |
||||||
|
import org.floens.chan.core.model.orm.Board; |
||||||
|
import org.floens.chan.core.site.Site; |
||||||
|
import org.floens.chan.utils.Time; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Observable; |
||||||
|
import java.util.Observer; |
||||||
|
|
||||||
|
import javax.inject.Inject; |
||||||
|
import javax.inject.Singleton; |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public class BoardRepository implements Observer { |
||||||
|
private final DatabaseManager databaseManager; |
||||||
|
private final DatabaseBoardManager databaseBoardManager; |
||||||
|
|
||||||
|
private final SiteRepository siteRepository; |
||||||
|
private final SiteRepository.Sites allSites; |
||||||
|
|
||||||
|
private SitesBoards allBoards = new SitesBoards(); |
||||||
|
private SitesBoards savedBoards = new SitesBoards(); |
||||||
|
|
||||||
|
@Inject |
||||||
|
public BoardRepository(DatabaseManager databaseManager, SiteRepository siteRepository) { |
||||||
|
this.databaseManager = databaseManager; |
||||||
|
databaseBoardManager = databaseManager.getDatabaseBoardManager(); |
||||||
|
|
||||||
|
this.siteRepository = siteRepository; |
||||||
|
|
||||||
|
allSites = this.siteRepository.all(); |
||||||
|
allSites.addObserver(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void initialize() { |
||||||
|
updateObservablesSync(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void update(Observable o, Object arg) { |
||||||
|
if (o == allSites) { |
||||||
|
updateObservablesAsync(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void updateAvailableBoardsForSite(Site site, List<Board> availableBoards) { |
||||||
|
databaseManager.runTask(databaseBoardManager.createAll(site, availableBoards)); |
||||||
|
} |
||||||
|
|
||||||
|
public Board getFromCode(Site site, String code) { |
||||||
|
for (SiteBoards siteBoards : allBoards.get()) { |
||||||
|
if (siteBoards.site.id() == site.id()) { |
||||||
|
for (Board board : siteBoards.boards) { |
||||||
|
if (board.code.equals(code)) { |
||||||
|
return board; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public SitesBoards getAll() { |
||||||
|
return allBoards; |
||||||
|
} |
||||||
|
|
||||||
|
public SitesBoards getSaved() { |
||||||
|
return savedBoards; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Board> getSiteBoards(Site site) { |
||||||
|
for (SiteBoards item : allBoards.siteBoards) { |
||||||
|
if (item.site.id() == site.id()) { |
||||||
|
return item.boards; |
||||||
|
} |
||||||
|
} |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Board> getSiteSavedBoards(Site site) { |
||||||
|
for (SiteBoards item : savedBoards.siteBoards) { |
||||||
|
if (item.site.id() == site.id()) { |
||||||
|
return item.boards; |
||||||
|
} |
||||||
|
} |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
|
||||||
|
public void updateBoardOrders(List<Board> boards) { |
||||||
|
databaseManager.runTaskAsync(databaseBoardManager.updateOrders(boards), |
||||||
|
(e) -> updateObservablesAsync()); |
||||||
|
} |
||||||
|
|
||||||
|
public void setSaved(Board board, boolean saved) { |
||||||
|
board.saved = saved; |
||||||
|
databaseManager.runTaskAsync(databaseBoardManager.updateIncludingUserFields(board), |
||||||
|
(e) -> updateObservablesAsync()); |
||||||
|
} |
||||||
|
|
||||||
|
public void setAllSaved(List<Board> boards, boolean saved) { |
||||||
|
for (Board board : boards) { |
||||||
|
board.saved = saved; |
||||||
|
} |
||||||
|
databaseManager.runTaskAsync(databaseBoardManager.updateIncludingUserFields(boards), |
||||||
|
(e) -> updateObservablesAsync()); |
||||||
|
} |
||||||
|
|
||||||
|
private void updateObservablesSync() { |
||||||
|
long start = Time.startTiming(); |
||||||
|
updateWith(databaseManager.runTask( |
||||||
|
databaseBoardManager.getBoardsForAllSitesOrdered(allSites.getAll()))); |
||||||
|
Time.endTiming("BoardRepository.updateObservablesSync", start); |
||||||
|
} |
||||||
|
|
||||||
|
private void updateObservablesAsync() { |
||||||
|
databaseManager.runTaskAsync( |
||||||
|
databaseBoardManager.getBoardsForAllSitesOrdered(allSites.getAll()), |
||||||
|
this::updateWith); |
||||||
|
} |
||||||
|
|
||||||
|
private void updateWith(List<Pair<Site, List<Board>>> databaseData) { |
||||||
|
List<SiteBoards> all = new ArrayList<>(); |
||||||
|
List<SiteBoards> saved = new ArrayList<>(); |
||||||
|
for (Pair<Site, List<Board>> item : databaseData) { |
||||||
|
all.add(new SiteBoards(item.first, item.second)); |
||||||
|
|
||||||
|
List<Board> savedBoards = new ArrayList<>(); |
||||||
|
for (Board board : item.second) { |
||||||
|
if (board.saved) savedBoards.add(board); |
||||||
|
} |
||||||
|
saved.add(new SiteBoards(item.first, savedBoards)); |
||||||
|
} |
||||||
|
|
||||||
|
allBoards.set(all); |
||||||
|
savedBoards.set(saved); |
||||||
|
|
||||||
|
allBoards.notifyObservers(); |
||||||
|
savedBoards.notifyObservers(); |
||||||
|
} |
||||||
|
|
||||||
|
public class SitesBoards extends Observable { |
||||||
|
private List<SiteBoards> siteBoards = new ArrayList<>(); |
||||||
|
|
||||||
|
public void set(List<SiteBoards> siteBoards) { |
||||||
|
this.siteBoards = siteBoards; |
||||||
|
setChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
public List<SiteBoards> get() { |
||||||
|
return siteBoards; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class SiteBoards { |
||||||
|
public final Site site; |
||||||
|
public final List<Board> boards; |
||||||
|
|
||||||
|
public SiteBoards(Site site, List<Board> boards) { |
||||||
|
this.site = site; |
||||||
|
this.boards = boards; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,249 @@ |
|||||||
|
package org.floens.chan.core.repository; |
||||||
|
|
||||||
|
import android.util.Pair; |
||||||
|
import android.util.SparseArray; |
||||||
|
|
||||||
|
import org.floens.chan.core.database.DatabaseManager; |
||||||
|
import org.floens.chan.core.model.json.site.SiteConfig; |
||||||
|
import org.floens.chan.core.model.orm.SiteModel; |
||||||
|
import org.floens.chan.core.settings.json.JsonSettings; |
||||||
|
import org.floens.chan.core.site.Site; |
||||||
|
import org.floens.chan.core.site.SiteRegistry; |
||||||
|
import org.floens.chan.core.site.sites.chan4.Chan4; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Observable; |
||||||
|
|
||||||
|
import javax.inject.Inject; |
||||||
|
import javax.inject.Singleton; |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public class SiteRepository { |
||||||
|
private DatabaseManager databaseManager; |
||||||
|
|
||||||
|
private Sites sitesObservable = new Sites(); |
||||||
|
|
||||||
|
// Shortcut
|
||||||
|
private static SiteRepository instance; |
||||||
|
|
||||||
|
public static Site forId(int id) { |
||||||
|
return instance.sitesObservable.forId(id); |
||||||
|
} |
||||||
|
|
||||||
|
@Inject |
||||||
|
public SiteRepository(DatabaseManager databaseManager) { |
||||||
|
instance = this; |
||||||
|
this.databaseManager = databaseManager; |
||||||
|
} |
||||||
|
|
||||||
|
public Sites all() { |
||||||
|
return sitesObservable; |
||||||
|
} |
||||||
|
|
||||||
|
public SiteModel byId(int id) { |
||||||
|
return databaseManager.runTask(databaseManager.getDatabaseSiteManager() |
||||||
|
.byId(id)); |
||||||
|
} |
||||||
|
|
||||||
|
public void setId(SiteModel siteModel, int id) { |
||||||
|
databaseManager.runTask(databaseManager.getDatabaseSiteManager() |
||||||
|
.updateId(siteModel, id)); |
||||||
|
} |
||||||
|
|
||||||
|
public void updateSiteUserSettingsAsync(SiteModel siteModel, JsonSettings jsonSettings) { |
||||||
|
siteModel.storeUserSettings(jsonSettings); |
||||||
|
databaseManager.runTaskAsync(databaseManager.getDatabaseSiteManager() |
||||||
|
.update(siteModel)); |
||||||
|
} |
||||||
|
|
||||||
|
public Map<Integer, Integer> getOrdering() { |
||||||
|
return databaseManager.runTask(databaseManager.getDatabaseSiteManager().getOrdering()); |
||||||
|
} |
||||||
|
|
||||||
|
public void updateSiteOrderingAsync(List<Site> sites) { |
||||||
|
List<Integer> ids = new ArrayList<>(sites.size()); |
||||||
|
for (Site site : sites) { |
||||||
|
ids.add(site.id()); |
||||||
|
} |
||||||
|
|
||||||
|
databaseManager.runTaskAsync( |
||||||
|
databaseManager.getDatabaseSiteManager().updateOrdering(ids), |
||||||
|
(r) -> { |
||||||
|
sitesObservable.wasReordered(); |
||||||
|
sitesObservable.notifyObservers(); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public void initialize() { |
||||||
|
List<Site> sites = new ArrayList<>(); |
||||||
|
|
||||||
|
List<SiteModel> models = databaseManager.runTask( |
||||||
|
databaseManager.getDatabaseSiteManager().getAll()); |
||||||
|
|
||||||
|
for (SiteModel siteModel : models) { |
||||||
|
SiteConfigSettingsHolder holder = instantiateSiteFromModel(siteModel); |
||||||
|
|
||||||
|
Site site = holder.site; |
||||||
|
SiteConfig config = holder.config; |
||||||
|
JsonSettings settings = holder.settings; |
||||||
|
|
||||||
|
site.initialize(siteModel.id, config, settings); |
||||||
|
|
||||||
|
sites.add(site); |
||||||
|
} |
||||||
|
|
||||||
|
sitesObservable.addAll(sites); |
||||||
|
|
||||||
|
for (Site site : sites) { |
||||||
|
site.postInitialize(); |
||||||
|
} |
||||||
|
|
||||||
|
sitesObservable.notifyObservers(); |
||||||
|
} |
||||||
|
|
||||||
|
// Called before #initialize to add the old 4chan site when the database was upgraded from
|
||||||
|
// an older version. It only adds the model to the database with id 0.
|
||||||
|
public void addLegacySite() { |
||||||
|
Site site = new Chan4(); |
||||||
|
|
||||||
|
SiteConfig config = new SiteConfig(); |
||||||
|
config.classId = SiteRegistry.SITE_CLASSES.indexOfValue(site.getClass()); |
||||||
|
config.external = false; |
||||||
|
|
||||||
|
SiteModel model = createFromClass(config, new JsonSettings()); |
||||||
|
setId(model, 0); |
||||||
|
} |
||||||
|
|
||||||
|
public Site createFromClass(Class<? extends Site> siteClass) { |
||||||
|
Site site = instantiateSiteClass(siteClass); |
||||||
|
|
||||||
|
SiteConfig config = new SiteConfig(); |
||||||
|
JsonSettings settings = new JsonSettings(); |
||||||
|
|
||||||
|
config.classId = SiteRegistry.SITE_CLASSES.indexOfValue(site.getClass()); |
||||||
|
config.external = false; |
||||||
|
|
||||||
|
SiteModel model = createFromClass(config, settings); |
||||||
|
|
||||||
|
site.initialize(model.id, config, settings); |
||||||
|
|
||||||
|
sitesObservable.add(site); |
||||||
|
|
||||||
|
site.postInitialize(); |
||||||
|
|
||||||
|
sitesObservable.notifyObservers(); |
||||||
|
|
||||||
|
return site; |
||||||
|
} |
||||||
|
|
||||||
|
private SiteModel createFromClass(SiteConfig config, JsonSettings userSettings) { |
||||||
|
SiteModel siteModel = new SiteModel(); |
||||||
|
siteModel.storeConfig(config); |
||||||
|
siteModel.storeUserSettings(userSettings); |
||||||
|
databaseManager.runTask(databaseManager.getDatabaseSiteManager().add(siteModel)); |
||||||
|
|
||||||
|
return siteModel; |
||||||
|
} |
||||||
|
|
||||||
|
private SiteConfigSettingsHolder instantiateSiteFromModel(SiteModel siteModel) { |
||||||
|
Pair<SiteConfig, JsonSettings> configFields = siteModel.loadConfigFields(); |
||||||
|
SiteConfig config = configFields.first; |
||||||
|
JsonSettings settings = configFields.second; |
||||||
|
|
||||||
|
return new SiteConfigSettingsHolder( |
||||||
|
instantiateSiteClass(config.classId), |
||||||
|
config, |
||||||
|
settings); |
||||||
|
} |
||||||
|
|
||||||
|
private Site instantiateSiteClass(int classId) { |
||||||
|
Class<? extends Site> clazz = SiteRegistry.SITE_CLASSES.get(classId); |
||||||
|
if (clazz == null) { |
||||||
|
throw new IllegalArgumentException("Unknown class id"); |
||||||
|
} |
||||||
|
return instantiateSiteClass(clazz); |
||||||
|
} |
||||||
|
|
||||||
|
private Site instantiateSiteClass(Class<? extends Site> clazz) { |
||||||
|
Site site; |
||||||
|
try { |
||||||
|
site = clazz.newInstance(); |
||||||
|
} catch (InstantiationException e) { |
||||||
|
throw new IllegalArgumentException(); |
||||||
|
} catch (IllegalAccessException e) { |
||||||
|
throw new IllegalArgumentException(); |
||||||
|
} |
||||||
|
return site; |
||||||
|
} |
||||||
|
|
||||||
|
public class Sites extends Observable { |
||||||
|
private List<Site> sites = Collections.unmodifiableList(new ArrayList<>()); |
||||||
|
private SparseArray<Site> sitesById = new SparseArray<>(); |
||||||
|
|
||||||
|
public Site forId(int id) { |
||||||
|
Site s = sitesById.get(id); |
||||||
|
if (s == null) { |
||||||
|
throw new IllegalArgumentException("No site with id (" + id + ")"); |
||||||
|
} |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Site> getAll() { |
||||||
|
return new ArrayList<>(sites); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Site> getAllInOrder() { |
||||||
|
Map<Integer, Integer> ordering = getOrdering(); |
||||||
|
|
||||||
|
List<Site> ordered = new ArrayList<>(sites); |
||||||
|
Collections.sort(ordered, |
||||||
|
(lhs, rhs) -> ordering.get(lhs.id()) - ordering.get(rhs.id())); |
||||||
|
|
||||||
|
return ordered; |
||||||
|
} |
||||||
|
|
||||||
|
private void addAll(List<Site> all) { |
||||||
|
List<Site> copy = new ArrayList<>(sites); |
||||||
|
copy.addAll(all); |
||||||
|
resetSites(copy); |
||||||
|
setChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
private void add(Site site) { |
||||||
|
List<Site> copy = new ArrayList<>(sites); |
||||||
|
copy.add(site); |
||||||
|
resetSites(copy); |
||||||
|
setChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
// We don't keep the order ourselves here, that's the task of listeners. Do notify the
|
||||||
|
// listeners.
|
||||||
|
private void wasReordered() { |
||||||
|
setChanged(); |
||||||
|
} |
||||||
|
|
||||||
|
private void resetSites(List<Site> newSites) { |
||||||
|
sites = Collections.unmodifiableList(newSites); |
||||||
|
SparseArray<Site> byId = new SparseArray<>(newSites.size()); |
||||||
|
for (Site newSite : newSites) { |
||||||
|
byId.put(newSite.id(), newSite); |
||||||
|
} |
||||||
|
sitesById = byId; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class SiteConfigSettingsHolder { |
||||||
|
Site site; |
||||||
|
SiteConfig config; |
||||||
|
JsonSettings settings; |
||||||
|
|
||||||
|
public SiteConfigSettingsHolder(Site site, SiteConfig config, JsonSettings settings) { |
||||||
|
this.site = site; |
||||||
|
this.config = config; |
||||||
|
this.settings = settings; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,63 +0,0 @@ |
|||||||
package org.floens.chan.core.site; |
|
||||||
|
|
||||||
import org.floens.chan.core.database.DatabaseManager; |
|
||||||
import org.floens.chan.core.model.json.site.SiteConfig; |
|
||||||
import org.floens.chan.core.model.orm.SiteModel; |
|
||||||
import org.floens.chan.core.settings.json.JsonSettings; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import javax.inject.Inject; |
|
||||||
|
|
||||||
public class SiteRepository { |
|
||||||
private DatabaseManager databaseManager; |
|
||||||
|
|
||||||
@Inject |
|
||||||
public SiteRepository(DatabaseManager databaseManager) { |
|
||||||
this.databaseManager = databaseManager; |
|
||||||
} |
|
||||||
|
|
||||||
public List<SiteModel> all() { |
|
||||||
return databaseManager.runTask(databaseManager.getDatabaseSiteManager().getAll()); |
|
||||||
} |
|
||||||
|
|
||||||
public SiteModel byId(int id) { |
|
||||||
return databaseManager.runTask(databaseManager.getDatabaseSiteManager() |
|
||||||
.byId(id)); |
|
||||||
} |
|
||||||
|
|
||||||
public SiteModel create(SiteConfig config, JsonSettings userSettings) { |
|
||||||
SiteModel siteModel = new SiteModel(); |
|
||||||
siteModel.storeConfig(config); |
|
||||||
siteModel.storeUserSettings(userSettings); |
|
||||||
databaseManager.runTask(databaseManager.getDatabaseSiteManager().add(siteModel)); |
|
||||||
return siteModel; |
|
||||||
} |
|
||||||
|
|
||||||
public void setId(SiteModel siteModel, int id) { |
|
||||||
databaseManager.runTask(databaseManager.getDatabaseSiteManager() |
|
||||||
.updateId(siteModel, id)); |
|
||||||
} |
|
||||||
|
|
||||||
public void updateSiteUserSettingsAsync(SiteModel siteModel, JsonSettings jsonSettings) { |
|
||||||
siteModel.storeUserSettings(jsonSettings); |
|
||||||
databaseManager.runTaskAsync(databaseManager.getDatabaseSiteManager() |
|
||||||
.update(siteModel)); |
|
||||||
} |
|
||||||
|
|
||||||
public Map<Integer, Integer> getOrdering() { |
|
||||||
return databaseManager.runTask(databaseManager.getDatabaseSiteManager().getOrdering()); |
|
||||||
} |
|
||||||
|
|
||||||
public void updateSiteOrderingAsync(List<Site> sites, Runnable done) { |
|
||||||
List<Integer> ids = new ArrayList<>(sites.size()); |
|
||||||
for (Site site : sites) { |
|
||||||
ids.add(site.id()); |
|
||||||
} |
|
||||||
|
|
||||||
databaseManager.runTaskAsync(databaseManager.getDatabaseSiteManager().updateOrdering(ids), |
|
||||||
result -> done.run()); |
|
||||||
} |
|
||||||
} |
|
@ -1,35 +0,0 @@ |
|||||||
package org.floens.chan.core.site; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
public class Sites { |
|
||||||
private static List<Site> ALL_SITES = Collections.unmodifiableList(new ArrayList<Site>()); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return all sites known in the system. |
|
||||||
* <p>This list is immutable. Changes to the known sites cause this function to return a new immutable list |
|
||||||
* with the site changes. |
|
||||||
* |
|
||||||
* @return list of sites known in the system. |
|
||||||
*/ |
|
||||||
public static List<Site> allSites() { |
|
||||||
return ALL_SITES; |
|
||||||
} |
|
||||||
|
|
||||||
public static Site forId(int id) { |
|
||||||
// TODO: better datastructure
|
|
||||||
for (Site site : ALL_SITES) { |
|
||||||
if (site.id() == id) { |
|
||||||
return site; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
static void initialize(List<Site> sites) { |
|
||||||
Sites.ALL_SITES = Collections.unmodifiableList(new ArrayList<>(sites)); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue