/***************************************************************************************
* Copyright (c) 2012 Kostas Spyropoulos <inigo.aldana@gmail.com> *
* *
* 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 com.ichi2.libanki.hooks;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.ichi2.anki.AnkiDroidApp;
import com.ichi2.libanki.LaTeX;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import timber.log.Timber;
public class Hooks {
public static Hooks sInstance;
private static Map<String, List<Hook>> hooks;
public static synchronized Hooks getInstance(Context context) {
if (sInstance == null) {
sInstance = new Hooks(context);
}
return sInstance;
}
private Hooks(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
hooks = new HashMap<>();
// Always-ON hooks
new FuriganaFilters().install(this);
new HintFilter().install(this);
new LaTeX().installHook(this);
new Leech().installHook(this);
// Preferences activated hooks
if (prefs.getBoolean("fixHebrewText", false)) {
HebrewFixFilter.install(this);
}
if (prefs.getBoolean("convertFenText", false)) {
ChessFilter.install(this);
}
if (prefs.getBoolean("advanced_statistics_enabled", false)) {
AdvancedStatistics.install(this);
}
}
/**
* Add a function to hook. Ignore if already on hook.
*
* @param hook The name of the hook.
* @param func A class implements interface Hook and contains the function to add.
*/
public void addHook(String hook, Hook func) {
if (!hooks.containsKey(hook) || hooks.get(hook) == null) {
hooks.put(hook, new ArrayList<Hook>());
}
boolean found = false;
for (Hook h : hooks.get(hook)) {
if (func.equals(h)) {
found = true;
break;
}
}
if (!found) {
hooks.get(hook).add(func);
}
}
/**
* Remove a function if is on hook.
*
* @param hook The name of the hook.
* @param func A class implements interface Hook and contains the function to remove.
*/
public void remHook(String hook, Hook func) {
if (hooks.containsKey(hook) && hooks.get(hook) != null) {
for (Hook h : hooks.get(hook)) {
if (func.equals(h)) {
hooks.get(hook).remove(h);
break;
}
}
}
}
/**
* Run all functions on hook.
*
* @param hook The name of the hook.
* @param args Variable arguments to be passed to the method runHook of each function on this hook.
*/
public void runHook(String hook, Object... args) {
List<Hook> _hook = hooks.get(hook);
String funcName = "";
if (_hook != null) {
try {
for (Hook func : _hook) {
funcName = func.getClass().getCanonicalName();
func.runHook(args);
}
} catch (Exception e) {
Timber.e(e, "Exception while running hook %s : %s", hook, funcName);
return;
}
}
}
/**
* Apply all functions on hook to arg and return the result.
*
* @param hook The name of the hook.
* @param arg The input to the filter on hook.
* @param args Variable arguments to be passed to the method runHook of each function on this hook.
*/
public static Object runFilter(String hook, Object arg, Object... args) {
if (hooks == null) {
Timber.e("Hooks object has not been initialized");
AnkiDroidApp.sendExceptionReport(new IllegalStateException("Hooks object uninitialized"), "Hooks.runFilter");
return arg;
}
List<Hook> _hook = hooks.get(hook);
String funcName = "";
if (_hook != null) {
try {
for (Hook func : _hook) {
funcName = func.getClass().getCanonicalName();
arg = func.runFilter(arg, args);
}
} catch (Exception e) {
Timber.e(e, "Exception while running hook %s : %s", hook, funcName);
return "Error in filter " + hook + ":" + funcName;
}
}
return arg;
}
}