package yuku.alkitab.base.model; import android.util.Log; import yuku.alkitab.base.S; import yuku.alkitab.base.ac.VersionsActivity; import yuku.alkitab.base.storage.YesReaderFactory; import yuku.alkitab.io.BibleReader; import yuku.alkitab.model.Version; import java.io.File; import java.lang.ref.SoftReference; import java.util.concurrent.ConcurrentHashMap; /** * Version that is defined in the database. * If the version is downloaded from a definition in the preset list, the {@link #preset_name} will be non-null. */ public class MVersionDb extends MVersion { public static final int DEFAULT_ORDERING_START = 100; public String filename; public String preset_name; public boolean cache_active; // so we don't need to keep reading/writing from/to db /** * The last-known update time of the version, so we can notify the user if their downloaded versions has update. * If this is 0, it means the version does not support update notification, because the version is converted from legacy version of this app, * or added from pdb/yes files manually. */ public int modifyTime; /** * VersionImpl instance cache, so we do not reinstantiate VersionImpl objects every time * we access versions. Especially when doing a version compare. */ static ConcurrentHashMap<String /* filename */, SoftReference<VersionImpl>> impl_cache = new ConcurrentHashMap<>(); /** * The version id for MVersionDb can be "preset/" followed by preset_name, * or "file/" followed by absolute path name of the yes file. * * Therefore, the id starting with "preset/" does not always indicate MVersionPreset, * since it probably indicate MVersionDb as well. */ @Override public String getVersionId() { if (preset_name != null) { return "preset/" + preset_name; } return "file/" + filename; } /** * Return the preset_name of a version id, if possible. Null otherwise. */ public static String presetNameFromVersionId(String versionId) { if (versionId != null && versionId.startsWith("preset/")) { return versionId.substring(7); } else { return null; } } @Override public Version getVersion() { if (hasDataFile()) { // check cache first final SoftReference<VersionImpl> ref = impl_cache.get(filename); if (ref != null) { final VersionImpl res = ref.get(); if (res != null) { return res; } } final BibleReader reader = YesReaderFactory.createYesReader(filename); if (reader == null) { Log.e(VersionsActivity.TAG, "YesReaderFactory failed to open the yes file"); return null; } final VersionImpl res = new VersionImpl(reader); // put to cache impl_cache.put(filename, new SoftReference<>(res)); return res; } else { // clear from cache if any impl_cache.remove(filename); return null; } } public void setActive(boolean active) { this.cache_active = active; S.getDb().setVersionActive(this, active); } @Override public boolean getActive() { return this.cache_active; } @Override public boolean hasDataFile() { final File f = new File(filename); return f.exists() && f.canRead(); } public static void clearVersionImplCache() { impl_cache.clear(); } }