com.github.kubatatami.judonetworking.observers.ObserverHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of judonetworking-observers Show documentation
Show all versions of judonetworking-observers Show documentation
Easy way of communicating to your servers.
The newest version!
package com.github.kubatatami.judonetworking.observers;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.database.DataSetObserver;
import android.os.Build;
import android.support.v4.app.FragmentActivity;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.ListView;
import android.widget.TextView;
import com.github.kubatatami.judonetworking.exceptions.JudoException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created with IntelliJ IDEA.
* User: jbogacki
* Date: 08.04.2013
* Time: 22:23
*/
public class ObserverHelper {
private List> dataObservers = new ArrayList<>();
private List> dataAdapters = new ArrayList<>();
private Map> viewObservers = new HashMap<>();
private static final String splitter = "\\.";
private static final Pattern pattern = Pattern.compile("\\[[^\\]]*\\]");
static final String convention = "Changed";
private Context context;
private static ObserverErrorLogger errorLogger;
private static Object dataObject;
static Class> dataClass;
public static void setDataObject(Object data) {
dataObject = data;
dataClass = data.getClass();
}
public static void setDataClass(Class> dataClass) {
dataObject = null;
ObserverHelper.dataClass = dataClass;
}
public ObserverHelper(Context context) {
this.context = context;
}
public static void setErrorLogger(ObserverErrorLogger errorLogger) {
ObserverHelper.errorLogger = errorLogger;
}
public void start(final android.support.v4.app.Fragment fragment, View view) {
startInternal(fragment, view);
}
public void start(final android.app.Fragment fragment, View view) {
startInternal(fragment, view);
}
public void start(final Activity activity, View view) {
startInternal(activity, view);
}
public void start(final FragmentActivity activity, View view) {
startInternal(activity, view);
}
protected ObserverSettings getSettingsAnnotation(Class> clazz) {
for (; clazz != null; clazz = clazz.getSuperclass()) {
ObserverSettings settings = clazz.getAnnotation(ObserverSettings.class);
if (settings != null) {
return settings;
}
}
return null;
}
@SuppressWarnings("unchecked")
protected void startInternal(final Object object, View view) {
ObserverSettings settings = getSettingsAnnotation(object.getClass());
if (settings != null) {
dataObservers.clear();
viewObservers.clear();
dataAdapters.clear();
if (settings.dataObservers() && ObserverHelper.dataClass != null) {
findDataObserver(object);
}
if (settings.tags() && view != null) {
findViewObserver(view, object);
}
}
}
private void findViewObserver(View view, Object object) {
if (view instanceof ViewGroup && !(view instanceof ListView) && !isFromFragment(view, object)) {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
View viewElem = group.getChildAt(i);
findViewObserver(viewElem, object);
}
} else {
linkViewObserver(view, object);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private boolean isFromFragment(View view, Object object) {
if (view.getId() == -1) {
return false;
}
if (object instanceof FragmentActivity) {
return ((FragmentActivity) object).getSupportFragmentManager().findFragmentById(view.getId()) != null;
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB && object instanceof Activity) {
return ((Activity) object).getFragmentManager().findFragmentById(view.getId()) != null;
} else {
return false;
}
}
@SuppressWarnings("unchecked")
private void linkViewObserver(final View view, final Object object) {
try {
if (view.getTag() != null && view.getTag() instanceof String) {
final String tag = (String) view.getTag();
final List results = findObservablesByTag(tag);
WrapObserver observer = new WrapObserver() {
@Override
public void update(Object data) {
try {
if (view instanceof TextView) {
TextView textView = (TextView) view;
String result = buildResult(tag.substring(1, tag.length() - 1), object);
textView.setText(result);
}
} catch (Exception e) {
ExceptionHandler.throwRuntimeException(e);
}
}
};
if (results.size() > 0) {
for (ObservableWrapper result : results) {
result.addObserver(observer);
viewObservers.put(view, new Pair<>(result, observer));
}
} else if (view instanceof TextView && tag.matches("\\[.*\\]")) {
TextView textView = (TextView) view;
String result = buildResult(tag.substring(1, tag.length() - 1), object);
textView.setText(result);
}
}
} catch (Exception e) {
ExceptionHandler.throwRuntimeException(e);
}
}
private String buildResult(String tag, Object object) throws IllegalAccessException, NoSuchFieldException {
Matcher matcher = pattern.matcher(tag);
while (matcher.find()) {
String res = matcher.group(0);
String key = res.substring(1, res.length() - 1);
if (key.substring(0, 1).equals(".")) {
Object field = getFieldFromObserver(key, ObserverHelper.dataObject);
tag = tag.replace(res, field != null ? field.toString() : "");
} else if (key.substring(0, 8).equals("@string/")) {
tag = tag.replace(res, getStringResource(key.substring(8)));
} else {
Object field = getFieldOrMethodValue(key, object);
tag = tag.replace(res, field != null ? field.toString() : "");
}
}
return tag;
}
private String getStringResource(String stringName) {
int resId = context.getResources().getIdentifier(stringName, "string", context.getApplicationContext().getPackageName());
return context.getString(resId);
}
private List findObservablesByTag(String tag) throws Exception {
List list = new ArrayList<>();
if (tag.matches("\\[.*\\]")) {
if (ObserverHelper.dataClass == null) {
throw new RuntimeException("No data object set. Use JsonObserver.setDataObject() method.");
}
tag = tag.substring(1, tag.length() - 1);
Matcher matcher = pattern.matcher(tag);
while (matcher.find()) {
String res = matcher.group(0);
res = res.substring(1, res.length() - 1);
if (res.substring(0, 1).equals(".")) {
String fields[] = res.split(splitter);
list.add((ObservableWrapper) ObservableCache.getField(fields[1]).get(ObserverHelper.dataObject));
}
}
}
return list;
}
@SuppressWarnings("unchecked")
private void findDataObserver(final Object object) {
for (final ObservableCache.DataObserverMethod observerMethod : ObservableCache.getDataObserverMethods(object.getClass())) {
try {
final Object wrapperOrAdapter = observerMethod.field.get(ObserverHelper.dataObject);
if (wrapperOrAdapter instanceof ObservableWrapper) {
final ObservableWrapper wrapper = (ObservableWrapper) wrapperOrAdapter;
WrapObserver observer = new WrapObserver() {
@Override
public void update(Object data) {
try {
if (data != null || wrapper.isAllowNull()) {
observerMethod.method.invoke(object, data);
}
} catch (Exception e) {
JudoException ex;
if (e.getCause() != null) {
ex = new JudoException(e.getCause());
ex.setStackTrace(e.getCause().getStackTrace());
} else {
ex = new JudoException(e);
}
if (observerMethod.dataObserver.crashable()) {
throw ex;
} else if (errorLogger != null) {
errorLogger.onError(ex);
}
}
}
};
wrapper.addObserver(observer, observerMethod.dataObserver.onStartup());
dataObservers.add(new Pair<>(wrapper, observer));
} else if (wrapperOrAdapter instanceof Adapter) {
final Adapter adapter = (Adapter) wrapperOrAdapter;
DataSetObserver dataSetObserver = new DataSetObserver() {
@Override
public void onChanged() {
Object param;
if (observerMethod.method.getParameterTypes()[0].isAssignableFrom(List.class)) {
List