mirror of https://github.com/kurisufriend/Clover
Added json models. Seperated normal models, orm models and json models packages.multisite
parent
e7f0038bbd
commit
345c22de7f
@ -0,0 +1,28 @@ |
|||||||
|
/* |
||||||
|
* 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.model.json.site; |
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName; |
||||||
|
|
||||||
|
public class SiteConfig { |
||||||
|
@SerializedName("external") |
||||||
|
public boolean external; |
||||||
|
|
||||||
|
@SerializedName("internal_site_id") |
||||||
|
public int classId; |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package org.floens.chan.core.site; |
||||||
|
|
||||||
|
|
||||||
|
public interface Resolvable { |
||||||
|
enum ResolveResult { |
||||||
|
NO, |
||||||
|
NAME_MATCH, |
||||||
|
FULL_MATCH |
||||||
|
} |
||||||
|
|
||||||
|
ResolveResult resolve(String value); |
||||||
|
|
||||||
|
Class<? extends Site> getSiteClass(); |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
/* |
||||||
|
* 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.site; |
||||||
|
|
||||||
|
|
||||||
|
import org.floens.chan.core.model.json.site.SiteConfig; |
||||||
|
import org.floens.chan.core.model.json.site.SiteUserSettings; |
||||||
|
|
||||||
|
public abstract class SiteBase implements Site { |
||||||
|
protected int id; |
||||||
|
protected SiteConfig config; |
||||||
|
protected SiteUserSettings userSettings; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initialize(int id, SiteConfig config, SiteUserSettings userSettings) { |
||||||
|
this.id = id; |
||||||
|
this.config = config; |
||||||
|
this.userSettings = userSettings; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int id() { |
||||||
|
return id; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,183 @@ |
|||||||
|
/* |
||||||
|
* 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.site; |
||||||
|
|
||||||
|
|
||||||
|
import android.util.Pair; |
||||||
|
|
||||||
|
import com.google.gson.Gson; |
||||||
|
|
||||||
|
import org.floens.chan.core.database.DatabaseManager; |
||||||
|
import org.floens.chan.core.model.json.site.SiteConfig; |
||||||
|
import org.floens.chan.core.model.json.site.SiteUserSettings; |
||||||
|
import org.floens.chan.core.model.orm.SiteModel; |
||||||
|
import org.floens.chan.core.site.sites.chan4.Chan4; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import javax.inject.Inject; |
||||||
|
import javax.inject.Singleton; |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public class SiteManager { |
||||||
|
@Inject |
||||||
|
DatabaseManager databaseManager; |
||||||
|
|
||||||
|
private SiteResolver resolver; |
||||||
|
|
||||||
|
private Gson gson = new Gson(); |
||||||
|
|
||||||
|
@Inject |
||||||
|
public SiteManager() { |
||||||
|
resolver = new SiteResolver(); |
||||||
|
} |
||||||
|
|
||||||
|
public void addSite(String url, SiteAddCallback callback) { |
||||||
|
SiteResolver.SiteResolverResult resolve = resolver.resolve(url); |
||||||
|
|
||||||
|
Site site; |
||||||
|
if (resolve.match == SiteResolver.SiteResolverResult.Match.BUILTIN) { |
||||||
|
site = instantiateSiteClass(resolve.builtinResult); |
||||||
|
} else if (resolve.match == SiteResolver.SiteResolverResult.Match.EXTERNAL) { |
||||||
|
callback.onSiteAddFailed("external todo"); |
||||||
|
return; |
||||||
|
} else { |
||||||
|
callback.onSiteAddFailed("not a url"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
site = createNewSite(site); |
||||||
|
|
||||||
|
List<Site> newAllSites = new ArrayList<>(Sites.ALL_SITES); |
||||||
|
newAllSites.add(site); |
||||||
|
Sites.initialize(newAllSites); |
||||||
|
|
||||||
|
callback.onSiteAdded(site); |
||||||
|
} |
||||||
|
|
||||||
|
public void initialize() { |
||||||
|
List<Site> sites = loadSitesFromDatabase(); |
||||||
|
|
||||||
|
if (sites.isEmpty()) { |
||||||
|
Site site = new Chan4(); |
||||||
|
|
||||||
|
SiteConfig config = new SiteConfig(); |
||||||
|
config.classId = Sites.SITE_CLASSES.indexOfValue(site.getClass()); |
||||||
|
config.external = false; |
||||||
|
|
||||||
|
SiteUserSettings userSettings = new SiteUserSettings(); |
||||||
|
|
||||||
|
SiteModel siteModel = new SiteModel(); |
||||||
|
storeConfigFields(siteModel, config, userSettings); |
||||||
|
siteModel = databaseManager.runTaskSync(databaseManager.getDatabaseSiteManager().add(siteModel)); |
||||||
|
databaseManager.runTaskSync(databaseManager.getDatabaseSiteManager().updateId(siteModel, 0)); |
||||||
|
|
||||||
|
sites.add(site); |
||||||
|
} |
||||||
|
|
||||||
|
Sites.initialize(sites); |
||||||
|
} |
||||||
|
|
||||||
|
private List<Site> loadSitesFromDatabase() { |
||||||
|
List<Site> sites = new ArrayList<>(); |
||||||
|
|
||||||
|
List<SiteModel> siteModels = databaseManager.runTaskSync(databaseManager.getDatabaseSiteManager().getAll()); |
||||||
|
|
||||||
|
for (SiteModel siteModel : siteModels) { |
||||||
|
Pair<SiteConfig, SiteUserSettings> configPair = loadConfigFields(siteModel); |
||||||
|
SiteConfig config = configPair.first; |
||||||
|
SiteUserSettings userSettings = configPair.second; |
||||||
|
|
||||||
|
Site site = loadSiteFromModel(siteModel, config, userSettings); |
||||||
|
sites.add(site); |
||||||
|
} |
||||||
|
|
||||||
|
return sites; |
||||||
|
} |
||||||
|
|
||||||
|
private Site createNewSite(Site site) { |
||||||
|
SiteConfig config = new SiteConfig(); |
||||||
|
config.classId = Sites.SITE_CLASSES.indexOfValue(site.getClass()); |
||||||
|
config.external = false; |
||||||
|
|
||||||
|
SiteUserSettings userSettings = new SiteUserSettings(); |
||||||
|
|
||||||
|
SiteModel siteModel = createNewSiteModel(site, config, userSettings); |
||||||
|
|
||||||
|
initializeSite(site, siteModel.id, config, userSettings); |
||||||
|
|
||||||
|
return site; |
||||||
|
} |
||||||
|
|
||||||
|
private SiteModel createNewSiteModel(Site site, SiteConfig config, SiteUserSettings userSettings) { |
||||||
|
SiteModel siteModel = new SiteModel(); |
||||||
|
storeConfigFields(siteModel, config, userSettings); |
||||||
|
siteModel = databaseManager.runTaskSync(databaseManager.getDatabaseSiteManager().add(siteModel)); |
||||||
|
return siteModel; |
||||||
|
} |
||||||
|
|
||||||
|
private void storeConfigFields(SiteModel siteModel, SiteConfig config, SiteUserSettings userSettings) { |
||||||
|
siteModel.configuration = gson.toJson(config); |
||||||
|
siteModel.userSettings = gson.toJson(userSettings); |
||||||
|
} |
||||||
|
|
||||||
|
private Pair<SiteConfig, SiteUserSettings> loadConfigFields(SiteModel siteModel) { |
||||||
|
SiteConfig config = gson.fromJson(siteModel.configuration, SiteConfig.class); |
||||||
|
SiteUserSettings userSettings = gson.fromJson(siteModel.userSettings, SiteUserSettings.class); |
||||||
|
return Pair.create(config, userSettings); |
||||||
|
} |
||||||
|
|
||||||
|
private Site loadSiteFromModel(SiteModel model, SiteConfig config, SiteUserSettings userSettings) { |
||||||
|
Site site = instantiateSiteFromConfig(config); |
||||||
|
return initializeSite(site, model.id, config, userSettings); |
||||||
|
} |
||||||
|
|
||||||
|
private Site initializeSite(Site site, int id, SiteConfig config, SiteUserSettings userSettings) { |
||||||
|
site.initialize(id, config, userSettings); |
||||||
|
return site; |
||||||
|
} |
||||||
|
|
||||||
|
private Site instantiateSiteFromConfig(SiteConfig siteConfig) { |
||||||
|
int siteClassId = siteConfig.classId; |
||||||
|
Class<? extends Site> clazz = Sites.SITE_CLASSES.get(siteClassId); |
||||||
|
if (clazz == null) { |
||||||
|
throw new IllegalArgumentException(); |
||||||
|
} |
||||||
|
return instantiateSiteClass(clazz); |
||||||
|
} |
||||||
|
|
||||||
|
private Site instantiateSiteClass(Class<? extends Site> clazz) { |
||||||
|
Site site; |
||||||
|
//noinspection TryWithIdenticalCatches
|
||||||
|
try { |
||||||
|
site = clazz.newInstance(); |
||||||
|
} catch (InstantiationException e) { |
||||||
|
throw new IllegalArgumentException(); |
||||||
|
} catch (IllegalAccessException e) { |
||||||
|
throw new IllegalArgumentException(); |
||||||
|
} |
||||||
|
return site; |
||||||
|
} |
||||||
|
|
||||||
|
public interface SiteAddCallback { |
||||||
|
void onSiteAdded(Site site); |
||||||
|
|
||||||
|
void onSiteAddFailed(String message); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
/* |
||||||
|
* 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.site; |
||||||
|
|
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import okhttp3.HttpUrl; |
||||||
|
|
||||||
|
class SiteResolver { |
||||||
|
SiteResolverResult resolve(String url) { |
||||||
|
List<Resolvable> resolvables = Sites.RESOLVABLES; |
||||||
|
|
||||||
|
HttpUrl httpUrl = HttpUrl.parse(url); |
||||||
|
|
||||||
|
if (httpUrl == null) { |
||||||
|
httpUrl = HttpUrl.parse("https://" + url); |
||||||
|
} |
||||||
|
|
||||||
|
if (httpUrl != null) { |
||||||
|
if (httpUrl.host().indexOf('.') < 0) { |
||||||
|
httpUrl = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (httpUrl == null) { |
||||||
|
for (Resolvable resolvable : resolvables) { |
||||||
|
if (resolvable.resolve(url) == Resolvable.ResolveResult.NAME_MATCH) { |
||||||
|
return new SiteResolverResult(SiteResolverResult.Match.BUILTIN, resolvable.getSiteClass(), null); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return new SiteResolverResult(SiteResolverResult.Match.NONE, null, null); |
||||||
|
} |
||||||
|
|
||||||
|
if (!httpUrl.scheme().equals("https")) { |
||||||
|
httpUrl = httpUrl.newBuilder().scheme("https").build(); |
||||||
|
} |
||||||
|
|
||||||
|
for (Resolvable resolvable : resolvables) { |
||||||
|
if (resolvable.resolve(httpUrl.toString()) == Resolvable.ResolveResult.FULL_MATCH) { |
||||||
|
return new SiteResolverResult(SiteResolverResult.Match.BUILTIN, resolvable.getSiteClass(), null); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return new SiteResolverResult(SiteResolverResult.Match.EXTERNAL, null, httpUrl); |
||||||
|
} |
||||||
|
|
||||||
|
static class SiteResolverResult { |
||||||
|
enum Match { |
||||||
|
NONE, |
||||||
|
BUILTIN, |
||||||
|
EXTERNAL |
||||||
|
} |
||||||
|
|
||||||
|
Match match; |
||||||
|
Class<? extends Site> builtinResult; |
||||||
|
HttpUrl externalResult; |
||||||
|
|
||||||
|
public SiteResolverResult(Match match, Class<? extends Site> builtinResult, HttpUrl externalResult) { |
||||||
|
this.match = match; |
||||||
|
this.builtinResult = builtinResult; |
||||||
|
this.externalResult = externalResult; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,44 +1,52 @@ |
|||||||
package org.floens.chan.core.site; |
package org.floens.chan.core.site; |
||||||
|
|
||||||
import android.content.SharedPreferences; |
import android.util.SparseArray; |
||||||
|
|
||||||
import org.floens.chan.core.site.sites.chan4.Chan4; |
import org.floens.chan.core.site.sites.chan4.Chan4; |
||||||
import org.floens.chan.utils.AndroidUtils; |
|
||||||
|
|
||||||
import java.util.Arrays; |
import java.util.ArrayList; |
||||||
import java.util.List; |
import java.util.List; |
||||||
|
|
||||||
public class Sites { |
public class Sites { |
||||||
public static final Chan4 CHAN4 = new Chan4(); |
public static final SparseArray<Class<? extends Site>> SITE_CLASSES = new SparseArray<>(); |
||||||
|
|
||||||
public static final List<? extends Site> ALL_SITES = Arrays.asList( |
static { |
||||||
CHAN4 |
// This id-siteclass mapping is used to look up the correct site class at deserialization.
|
||||||
); |
// This differs from the Site.id() id, that id is used for site instance linking, this is just to
|
||||||
|
// find the correct class to use.
|
||||||
|
SITE_CLASSES.put(0, Chan4.class); |
||||||
|
} |
||||||
|
|
||||||
private static final Site[] BY_ID; |
public static final List<Resolvable> RESOLVABLES = new ArrayList<>(); |
||||||
|
|
||||||
static { |
static { |
||||||
int highestId = 0; |
RESOLVABLES.add(Chan4.RESOLVABLE); |
||||||
|
} |
||||||
|
|
||||||
|
public static final List<Site> ALL_SITES = new ArrayList<>(); |
||||||
|
|
||||||
|
@Deprecated |
||||||
|
private static Site defaultSite; |
||||||
|
|
||||||
|
public static Site forId(int id) { |
||||||
|
// TODO: better datastructure
|
||||||
for (Site site : ALL_SITES) { |
for (Site site : ALL_SITES) { |
||||||
if (site.id() > highestId) { |
if (site.id() == id) { |
||||||
highestId = site.id(); |
return site; |
||||||
} |
} |
||||||
} |
} |
||||||
BY_ID = new Site[highestId + 1]; |
|
||||||
for (Site site : ALL_SITES) { |
|
||||||
BY_ID[site.id()] = site; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static Site forId(int id) { |
return null; |
||||||
return BY_ID[id]; |
|
||||||
} |
} |
||||||
|
|
||||||
|
@Deprecated |
||||||
public static Site defaultSite() { |
public static Site defaultSite() { |
||||||
return CHAN4; |
return defaultSite; |
||||||
} |
} |
||||||
|
|
||||||
public static SharedPreferences getPreferences(Site site) { |
static void initialize(List<Site> sites) { |
||||||
return AndroidUtils.getPreferences(site.id() + "_site_preferences"); |
Sites.defaultSite = sites.isEmpty() ? null : sites.get(0); |
||||||
|
Sites.ALL_SITES.clear(); |
||||||
|
Sites.ALL_SITES.addAll(sites); |
||||||
} |
} |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue