GlobalConfig and create node data storage

This commit is contained in:
GabrielBRDeveloper 2023-12-14 12:55:28 -04:00
parent eb23d7eab3
commit f553e80080
9 changed files with 461 additions and 0 deletions

View file

@ -11,6 +11,7 @@
android:glEsVersion="0x0030001"/>
<application
android:name=".app.PandaApplication"
android:requestLegacyExternalStorage="true"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"

View file

@ -0,0 +1,21 @@
package com.panda3ds.pandroid.app;
import android.app.Application;
import android.content.Context;
import com.panda3ds.pandroid.data.config.GlobalConfig;
public class PandaApplication extends Application {
private static Context appContext;
@Override
public void onCreate() {
super.onCreate();
appContext = this;
GlobalConfig.initialize();
}
public static Context getAppContext() {
return appContext;
}
}

View file

@ -0,0 +1,61 @@
package com.panda3ds.pandroid.data.config;
import android.content.Context;
import android.content.SharedPreferences;
import com.panda3ds.pandroid.app.PandaApplication;
import com.panda3ds.pandroid.utils.Constants;
import java.io.Serializable;
public class GlobalConfig {
private static SharedPreferences data;
public static void initialize() {
data = PandaApplication.getAppContext()
.getSharedPreferences(Constants.PREF_GLOBAL_CONFIG, Context.MODE_PRIVATE);
}
private static <T extends Serializable> T get(Key<T> key) {
Serializable value;
if (key.defValue instanceof String) {
value = data.getString(key.name, (String) key.defValue);
} else if (key.defValue instanceof Integer) {
value = data.getInt(key.name, (int) key.defValue);
} else if (key.defValue instanceof Boolean) {
value = data.getBoolean(key.name, (Boolean) key.defValue);
} else if (key.defValue instanceof Long) {
value = data.getLong(key.name, (Long) key.defValue);
} else {
value = data.getFloat(key.name, ((Number) key.defValue).floatValue());
}
return (T) value;
}
//Need synchronized why SharedPreferences don't support aysnc write
private static synchronized <T extends Serializable> void set(Key<T> key, T value) {
if (value instanceof String) {
data.edit().putString(key.name, (String) value).apply();
} else if (value instanceof Integer) {
data.edit().putInt(key.name, (Integer) value).apply();
} else if (value instanceof Boolean) {
data.edit().putBoolean(key.name, (Boolean) value).apply();
} else if (value instanceof Long) {
data.edit().putLong(key.name, (Long) value).apply();
} else if (value instanceof Float) {
data.edit().putFloat(key.name, (Float) value).apply();
} else {
throw new IllegalArgumentException("Invalid global config value instance");
}
}
private static class Key<T extends Serializable> {
private final String name;
private final T defValue;
private Key(String name, T defValue) {
this.name = name;
this.defValue = defValue;
}
}
}

View file

@ -0,0 +1,40 @@
package com.panda3ds.pandroid.data.node;
/**
* JAVA THINGS:
* Java allow cast primary (int, double, float and long)
* but crash on cast object number why!!
**/
class Caster {
public static int intValue(Object value){
if (value instanceof Number){
return ((Number)value).intValue();
} else {
return Integer.parseInt((String) value);
}
}
public static float floatValue(Object value){
if (value instanceof Number){
return ((Number)value).floatValue();
} else {
return Float.parseFloat((String) value);
}
}
public static long longValue(Object value){
if (value instanceof Number){
return ((Number)value).longValue();
} else {
return Long.parseLong((String) value);
}
}
public static double doubleValue(Object value){
if (value instanceof Number){
return ((Number)value).doubleValue();
} else {
return Double.parseDouble((String) value);
}
}
}

View file

@ -0,0 +1,133 @@
package com.panda3ds.pandroid.data.node;
import androidx.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class NodeArray extends NodeBase {
public static final String EMPTY_SOURCE = "[]";
private final ArrayList<Object> list = new ArrayList<>();
NodeArray(JSONArray array) {
init(array);
}
public NodeArray() {
this(EMPTY_SOURCE);
}
public NodeArray(String source) {
try {
init(new JSONArray(source));
} catch (JSONException e) {
throw new IllegalArgumentException(e);
}
}
private void init(JSONArray array) {
try {
for (int i = 0; i < array.length(); i++) {
Object item = array.get(i);
if (item instanceof JSONArray) {
item = new NodeArray((JSONArray) item);
((NodeArray) item).setParent(this);
} else if (item instanceof JSONObject) {
item = new NodeObject((JSONObject) item);
((NodeObject) item).setParent(this);
}
list.add(item);
}
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
private void add(Object obj) {
list.add(obj);
changed();
}
public String getString(int index) {
return (String) list.get(index);
}
public int getInteger(int index) {
return Caster.intValue(list.get(index));
}
public long getLong(int index) {
return Caster.longValue(list.get(index));
}
public boolean getBoolean(int index) {
return (boolean) list.get(index);
}
public double getDouble(int index) {
return Caster.doubleValue(list.get(index));
}
public NodeArray getArray(int index) {
return (NodeArray) list.get(index);
}
public NodeObject getObject(int index) {
return (NodeObject) list.get(index);
}
public void add(String val) {
list.add(val);
}
public void add(int val) {
add((Object) val);
}
public void add(long val) {
add((Object) val);
}
public void add(double val) {
add((Object) val);
}
public void add(boolean val) {
add((Object) val);
}
public void add(NodeBase val) {
add((Object) val);
}
public int getSize() {
return list.size();
}
@NonNull
@Override
public String toString() {
try {
return ((JSONArray) buildValue()).toString(4);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
@Override
protected Object buildValue() {
JSONArray array = new JSONArray();
for (Object obj : list) {
if (obj instanceof NodeBase) {
array.put(((NodeBase) obj).buildValue());
} else {
array.put(obj);
}
}
return array;
}
}

View file

@ -0,0 +1,34 @@
package com.panda3ds.pandroid.data.node;
import androidx.annotation.NonNull;
import com.panda3ds.pandroid.lang.Function;
abstract class NodeBase {
private NodeBase parent = null;
private Function<NodeBase> changeListener;
protected void setParent(NodeBase parent) {
this.parent = parent;
}
protected void changed() {
if (parent != null)
parent.changed();
if (changeListener != null)
changeListener.run(this);
}
public <T extends NodeBase> void setChangeListener(Function<T> listener) {
changeListener = val -> listener.run((T) val);
}
protected NodeBase getParent() {
return parent;
}
protected abstract Object buildValue();
@NonNull
public abstract String toString();
}

View file

@ -0,0 +1,164 @@
package com.panda3ds.pandroid.data.node;
import androidx.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Iterator;
public class NodeObject extends NodeBase {
public static final String EMPTY_SOURCE = "{}";
private final HashMap<String, Object> map = new HashMap<>();
NodeObject(JSONObject obj) {
init(obj);
}
public NodeObject() {
this(EMPTY_SOURCE);
}
public NodeObject(String source) {
try {
init(new JSONObject(source));
} catch (JSONException e) {
throw new IllegalArgumentException(e);
}
}
private void init(JSONObject base) {
try {
Iterator<String> keys = base.keys();
while (keys.hasNext()) {
String key = keys.next();
Object item = base.get(key);
if (item instanceof JSONObject) {
item = new NodeObject((JSONObject) item);
((NodeObject) item).setParent(this);
} else if (item instanceof JSONArray) {
item = new NodeArray((JSONArray) item);
((NodeArray) item).setParent(this);
}
map.put(key, item);
}
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
private Object get(String key, Object def) {
if (!has(key))
return def;
return map.get(key);
}
private void put(String key, Object value) {
map.put(key, value);
changed();
}
public String getString(String key, String def) {
return (String) get(key, def);
}
public int getInteger(String key, int def) {
return Caster.intValue(get(key, def));
}
public long getLong(String key, long def) {
return Caster.longValue(get(key, def));
}
public boolean getBoolean(String key, boolean def) {
return (boolean) get(key, def);
}
public double getDouble(String key, double def) {
return Caster.doubleValue(get(key, def));
}
public NodeArray getArray(String key, NodeArray def) {
return (NodeArray) get(key, def);
}
public NodeObject getObject(String key, NodeObject def) {
return (NodeObject) get(key, def);
}
public void put(String key, String val) {
put(key, (Object) val);
}
public void put(String key, int val) {
put(key, (Object) val);
}
public void put(String key, double val) {
put(key, (Object) val);
}
public void put(String key, boolean val) {
put(key, (Object) val);
}
public void put(String key, NodeBase val) {
put(key, (Object) val);
}
public boolean has(String key) {
return map.containsKey(key);
}
public void remove(String key) {
map.remove(key);
changed();
}
public void clear() {
map.clear();
changed();
}
public String[] getKeys() {
return map.keySet().toArray(new String[0]);
}
public int getSize() {
return map.size();
}
@NonNull
@Override
public String toString() {
try {
return ((JSONObject) buildValue()).toString(4);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
@Override
protected Object buildValue() {
try {
JSONObject dest = new JSONObject();
for (String key : getKeys()) {
Object obj = map.get(key);
if (obj instanceof NodeBase) {
obj = ((NodeBase) obj).buildValue();
}
dest.put(key, obj);
}
return dest;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,5 @@
package com.panda3ds.pandroid.lang;
public interface Function<T> {
void run(T val);
}

View file

@ -20,4 +20,6 @@ public class Constants {
public static final String ACTIVITY_PARAMETER_PATH = "path";
public static final String LOG_TAG = "pandroid";
public static final String PREF_GLOBAL_CONFIG = "app.GlobalConfig";
}