/* This file is part of SlumDroid <https://github.com/slumdroid/slumdroid>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3
* as published by the Free Software Foundation.
*
* 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 <http://www.gnu.org/licenses/gpl-3.0.txt>
* for more details.
*
* Copyright (C) 2012-2016 Gennaro Imparato
*/
package it.slumdroid.tool;
import static it.slumdroid.droidmodels.model.InteractionType.CLICK;
import static it.slumdroid.droidmodels.model.InteractionType.ENTER_TEXT;
import static it.slumdroid.droidmodels.model.InteractionType.WRITE_TEXT;
import static it.slumdroid.droidmodels.model.SimpleType.BUTTON;
import static it.slumdroid.droidmodels.model.SimpleType.CHECKBOX;
import static it.slumdroid.droidmodels.model.SimpleType.CHECKTEXT;
import static it.slumdroid.droidmodels.model.SimpleType.IMAGE_VIEW;
import static it.slumdroid.droidmodels.model.SimpleType.MENU_ITEM;
import static it.slumdroid.droidmodels.model.SimpleType.NUMBER_PICKER_BUTTON;
import static it.slumdroid.droidmodels.model.SimpleType.RADIO;
import static it.slumdroid.droidmodels.model.SimpleType.TAB_VIEW;
import static it.slumdroid.droidmodels.model.SimpleType.TOGGLE_BUTTON;
import static it.slumdroid.tool.Resources.EVENTS;
import static it.slumdroid.tool.Resources.EXTRA_EVENTS;
import static it.slumdroid.tool.Resources.EXTRA_INPUTS;
import static it.slumdroid.tool.Resources.INPUTS;
import static it.slumdroid.tool.Resources.TAG;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.prefs.Preferences;
import android.annotation.SuppressLint;
import android.util.Log;
import it.slumdroid.tool.utilities.UserFactory;
import it.slumdroid.tool.utilities.adapters.SimpleInteractorAdapter;
import it.slumdroid.tool.utilities.interactors.editor.AdditionalEnterEditor;
import it.slumdroid.tool.utilities.interactors.editor.AdditionalWriteEditor;
// TODO: Auto-generated Javadoc
/**
* The Class Prefs.
*/
public class Prefs {
/** The prefs. */
private static Preferences prefs;
/** The not found. */
private static boolean notFound = false;
/** The local prefs. */
private Preferences localPrefs;
/** The resources. */
private Class<?> resources;
/** The main node. */
private static String mainNode = Prefs.class.getPackage().getName();
/** The additional events. */
public static ArrayList<SimpleInteractorAdapter> ADDITIONAL_EVENTS = new ArrayList<SimpleInteractorAdapter>();
/** The additional inputs. */
public static ArrayList<SimpleInteractorAdapter> ADDITIONAL_INPUTS = new ArrayList<SimpleInteractorAdapter>();
/**
* Instantiates a new prefs.
*
* @param node the node
*/
protected Prefs(String node) {
this.localPrefs = loadNode(node);
this.resources = Resources.class;
}
/**
* Gets the main node.
*
* @return the main node
*/
protected static Preferences getMainNode() {
if (notFound) {
return null;
}
if (prefs == null) {
loadMainNode();
}
return prefs;
}
/**
* Load main node.
*/
protected static void loadMainNode() {
loadMainNode(mainNode);
}
/**
* Load main node.
*
* @param node the node
*/
@SuppressLint("SdCardPath")
protected static void loadMainNode(String node) {
String path = "/data/data/" + mainNode + "/files/preferences.xml";
if (!(new File(path).exists())) {
Log.i(TAG, "Preferences file not found.");
notFound = true;
return;
}
try {
InputStream is = new BufferedInputStream(new FileInputStream(path));
Preferences.importPreferences(is);
} catch (Exception e) {
e.printStackTrace();
}
prefs = Preferences.userRoot().node(node);
}
/**
* Load node.
*
* @param localNode the local node
* @return the preferences
*/
protected static Preferences loadNode(String localNode) {
if (getMainNode() == null) {
return null;
}
return getMainNode().node(localNode);
}
/**
* Checks for prefs.
*
* @return true, if successful
*/
protected boolean hasPrefs() {
return this.localPrefs != null;
}
/**
* Update resources.
*/
protected void updateResources() {
if (!hasPrefs()) {
return;
}
for (Field parameter: this.resources.getFields()) {
if (Modifier.isFinal(parameter.getModifiers())) continue;
try {
updateValue(parameter);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Gets the int.
*
* @param parameter the parameter
* @return the int
* @throws IllegalArgumentException the illegal argument exception
* @throws IllegalAccessException the illegal access exception
*/
protected int getInt(Field parameter) throws IllegalArgumentException, IllegalAccessException {
return this.localPrefs.getInt(parameter.getName(), parameter.getInt(parameter));
}
/**
* Gets the long.
*
* @param parameter the parameter
* @return the long
* @throws IllegalArgumentException the illegal argument exception
* @throws IllegalAccessException the illegal access exception
*/
protected long getLong(Field parameter) throws IllegalArgumentException, IllegalAccessException {
return this.localPrefs.getLong(parameter.getName(), parameter.getLong(parameter));
}
/**
* Gets the boolean.
*
* @param parameter the parameter
* @return the boolean
* @throws IllegalArgumentException the illegal argument exception
* @throws IllegalAccessException the illegal access exception
*/
protected boolean getBoolean(Field parameter) throws IllegalArgumentException, IllegalAccessException {
return this.localPrefs.getBoolean(parameter.getName(), parameter.getBoolean(parameter));
}
/**
* Gets the string.
*
* @param parameter the parameter
* @return the string
* @throws IllegalArgumentException the illegal argument exception
* @throws IllegalAccessException the illegal access exception
*/
protected String getString(Field parameter) throws IllegalArgumentException, IllegalAccessException {
return this.localPrefs.get(parameter.getName(), parameter.get("").toString());
}
/**
* From array.
*
* @param parameter the parameter
* @param index the index
* @return the string
*/
protected static String fromArray(Field parameter, int index) {
return parameter.getName() + "[" + index + "]";
}
/**
* Gets the string array.
*
* @param parameter the parameter
* @return the string array
* @throws IllegalArgumentException the illegal argument exception
*/
protected String[] getStringArray(Field parameter) throws IllegalArgumentException {
List<String> theList = new ArrayList<String>();
int index = 0;
String value = new String();
boolean found = false;
while ((value = this.localPrefs.get(fromArray(parameter, index), null)) != null) {
found = true;
theList.add(value);
index++;
}
String tmp[] = new String[theList.size()];
return (found)?theList.toArray(tmp):null;
}
/**
* Gets the int array.
*
* @param parameter the parameter
* @return the int array
* @throws IllegalArgumentException the illegal argument exception
*/
protected int[] getIntArray(Field parameter) throws IllegalArgumentException {
String[] value = getStringArray(parameter);
if (value == null) {
return null;
}
int[] ret = new int[value.length];
for (int i = 0; i < value.length; i++) {
ret[i] = Integer.parseInt(value[i]);
}
return ret;
}
/**
* Sets the array.
*
* @param parameter the new array
* @throws IllegalArgumentException the illegal argument exception
* @throws IllegalAccessException the illegal access exception
*/
protected void setArray(Field parameter) throws IllegalArgumentException, IllegalAccessException {
setArray(parameter, parameter.getType());
}
/**
* Sets the array.
*
* @param parameter the parameter
* @param type the type
* @throws IllegalArgumentException the illegal argument exception
* @throws IllegalAccessException the illegal access exception
*/
protected void setArray(Field parameter, Class<?> type) throws IllegalArgumentException, IllegalAccessException {
Class<?> component = type.getComponentType();
if (component.equals(String.class)) {
String[] strings = getStringArray(parameter);
if (strings != null) {
parameter.set(parameter, strings);
}
} else if (component.equals(int.class)) {
int[] numbers = getIntArray(parameter);
if (numbers != null) {
parameter.set(parameter, numbers);
}
}
}
/**
* Update value.
*
* @param parameter the parameter
* @throws IllegalArgumentException the illegal argument exception
* @throws IllegalAccessException the illegal access exception
*/
protected void updateValue(Field parameter) throws IllegalArgumentException, IllegalAccessException {
Class<?> type = parameter.getType();
if (type.equals(int.class)) {
parameter.setInt(parameter, getInt(parameter));
} else if (type.equals(long.class)) {
parameter.setLong(parameter, getLong(parameter));
} else if (type.equals(String.class)) {
parameter.set(parameter, getString(parameter));
} else if (type.equals(boolean.class)) {
parameter.setBoolean(parameter, getBoolean(parameter));
} else if (type.isArray()) {
setArray(parameter, type);
} else {
return;
}
}
/**
* Update nodes.
*/
public static void updateNodes() {
updateNode("");
updateNode("automation");
updateNode("comparator");
updateNode("interactions");
checkEvents();
checkInputs();
}
/**
* Update node.
*
* @param node the node
*/
private static void updateNode(String node) {
new Prefs(node).updateResources();
}
/**
* Check inputs.
*/
private static void checkInputs() {
if (INPUTS != null) {
if (!hasClickAsInputs()) {
UserFactory.addInput(CLICK, RADIO, CHECKBOX, CHECKTEXT, TOGGLE_BUTTON, NUMBER_PICKER_BUTTON);
}
} else {
UserFactory.addInput(CLICK, RADIO, CHECKBOX, CHECKTEXT, TOGGLE_BUTTON, NUMBER_PICKER_BUTTON);
}
if (EXTRA_INPUTS != null) {
ADDITIONAL_INPUTS.clear();
for (String s: EXTRA_INPUTS) {
String[] widgets = s.split(",");
if (widgets[0].equals(WRITE_TEXT)) {
SimpleInteractorAdapter interactor = new AdditionalWriteEditor().addIdValuePair(widgets[1], Arrays.copyOfRange(widgets, 2, widgets.length));
ADDITIONAL_INPUTS.add(interactor);
}
}
}
}
/**
* Checks for click as inputs.
*
* @return true, if successful
*/
private static boolean hasClickAsInputs() {
boolean isClick = false;
for (String input: INPUTS) {
String[] widgets = input.split("( )?,( )?");
if (widgets[0].equals(CLICK)) {
isClick = true;
}
UserFactory.addInput(widgets[0], Arrays.copyOfRange(widgets, 1, widgets.length));
}
return isClick;
}
/**
* Check events.
*/
private static void checkEvents() {
if (EVENTS != null) {
if (!hasClickAsEvents()) {
UserFactory.addEvent(CLICK, BUTTON, MENU_ITEM, IMAGE_VIEW, TAB_VIEW);
}
} else {
UserFactory.addEvent(CLICK, BUTTON, MENU_ITEM, IMAGE_VIEW, TAB_VIEW);
}
if (EXTRA_EVENTS != null) {
ADDITIONAL_EVENTS.clear();
for (String event: EXTRA_EVENTS) {
String[] widgets = event.split(",");
if (widgets[0].equals(WRITE_TEXT)) {
SimpleInteractorAdapter interactor = new AdditionalWriteEditor().addIdValuePair(widgets[1], Arrays.copyOfRange(widgets, 2, widgets.length));
ADDITIONAL_EVENTS.add(interactor);
} else {
if (widgets[0].equals(ENTER_TEXT)) {
SimpleInteractorAdapter interactor = new AdditionalEnterEditor().addIdValuePair(widgets[1], Arrays.copyOfRange(widgets, 2, widgets.length));
ADDITIONAL_EVENTS.add(interactor);
}
}
}
}
}
/**
* Checks for click as events.
*
* @return true, if successful
*/
private static boolean hasClickAsEvents() {
boolean isClick = false;
for (String event: EVENTS) {
String[] widgets = event.split("( )?,( )?");
if (widgets[0].equals(CLICK)) {
isClick = true;
}
UserFactory.addEvent(widgets[0], Arrays.copyOfRange(widgets, 1, widgets.length));
}
return isClick;
}
}