All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.WazaBe.HoloEverywhere.Setting Maven / Gradle / Ivy

The newest version!
package com.WazaBe.HoloEverywhere;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.util.Log;

public abstract class Setting> {
	public static class BooleanProperty extends Property {
		@Override
		protected void onSetDefaultValue(SettingProperty settingProperty) {
			setValue(settingProperty.defaultBoolean());
		}
	}

	public static class EnumProperty> extends Property {
		private String defaultValue;

		@SuppressWarnings("unchecked")
		@Override
		protected void onSetDefaultValue(SettingProperty settingProperty) {
			defaultValue = settingProperty.defaultEnum();
			Class t = settingProperty.enumClass();
			Class clazz = t == NullEnum.class ? null : (Class) t;
			if (clazz != null) {
				setEnumClass(clazz);
			}
		}

		@SuppressWarnings("unchecked")
		public void setEnumClass(Class clazz) {
			if (defaultValue != null) {
				try {
					Method method = clazz.getMethod("valueOf", String.class);
					method.setAccessible(true);
					setValue((T) method.invoke(null, defaultValue));
				} catch (Exception e) {
					Log.w(Setting.TAG, "Error on getting enum value", e);
				}
			}
		}
	}

	public static class IntegerProperty extends Property {
		@Override
		protected void onSetDefaultValue(SettingProperty settingProperty) {
			setValue(settingProperty.defaultInt());
		}
	}

	private static enum NullEnum {

	}

	public static class Property {
		private Setting setting;
		private Z value;
		private boolean wasAttach = false;

		public void attach(Setting setting) {
			if (setting != null) {
				setting.attach(this);
			}
		}

		public void detach() {
			if (setting != null) {
				setting.detach(this);
			}
		}

		public final Setting getSetting() {
			return setting;
		}

		public Z getValue() {
			return value;
		}

		public boolean isValid() {
			return true;
		}

		public final void notifyOnChange() {
			if (setting != null) {
				setting.onPropertyChange(this);
			}
		}

		protected void onAttach(Setting setting) {

		}

		protected void onDetach() {

		}

		protected void onSetDefaultValue(SettingProperty settingProperty) {

		}

		private final void setSetting(Setting setting) {
			this.setting = setting;
			if (setting != null) {
				if (wasAttach) {
					onDetach();
				}
				onAttach(setting);
				wasAttach = true;
			} else if (wasAttach) {
				onDetach();
				wasAttach = false;
			}
		}

		public void setValue(Z value) {
			if (this.value != value) {
				this.value = value;
				notifyOnChange();
			}
		}
	}

	public static interface SettingListener> {
		public void onAttach(T setting);

		public void onDetach(T setting);

		public void onPropertyChange(T setting, Property property);
	}

	@Retention(RetentionPolicy.RUNTIME)
	@Target(ElementType.FIELD)
	public static @interface SettingProperty {
		public boolean create() default false;

		public boolean defaultBoolean() default false;

		public String defaultEnum() default "";

		public int defaultInt() default 0;

		public String defaultString() default "";

		public Class> enumClass() default NullEnum.class;
	}

	public static class StringProperty extends Property {
		@Override
		protected void onSetDefaultValue(SettingProperty settingProperty) {
			setValue(settingProperty.defaultString());
		}
	}

	private static final Map>, Setting> settingMap = new HashMap>, Setting>();

	private static final String TAG = Setting.class.getSimpleName();

	public static > void addListener(Class clazz,
			SettingListener settingListener) {
		Setting.get(clazz).addListener(settingListener);
	}

	@SuppressWarnings("unchecked")
	public static > T get(Class clazz) {
		if (!Setting.settingMap.containsKey(clazz)) {
			try {
				T t = clazz.newInstance();
				Setting.settingMap.put(clazz, t);
				t.init();
			} catch (Exception e) {
				Log.e(Setting.TAG, "Error init setting instance", e);
			}
		}
		return (T) Setting.settingMap.get(clazz);
	}

	public static > void removeListener(Class clazz,
			SettingListener settingListener) {
		if (Setting.settingMap.containsKey(clazz)) {
			Setting.get(clazz).removeListener(settingListener);
		}
	}

	private final List> listeners = new ArrayList>();

	private final List> propertyList = new ArrayList>();

	@SuppressWarnings("unchecked")
	public final T addListener(SettingListener listener) {
		if (listener == null) {
			throw new IllegalArgumentException("SettingListener can't be null");
		}
		if (!listeners.contains(listener)) {
			listeners.add(listener);
			listener.onAttach((T) this);
		} else {
			listeners.remove(listener);
			listeners.add(listener);
		}
		return (T) this;
	}

	@SuppressWarnings("unchecked")
	public final T attach(Property property) {
		if (property == null || !property.isValid()) {
			throw new RuntimeException("Property not valid");
		}
		if (property.getSetting() != null && property.getSetting() != this) {
			throw new RuntimeException("Property already attached to "
					+ property.getSetting().getClass().getName());
		}
		property.setSetting(this);
		propertyList.add(property);
		return (T) this;
	}

	@SuppressWarnings("unchecked")
	public final T detach(Property property) {
		if (property != null) {
			propertyList.remove(property);
			property.setSetting(null);
		}
		return (T) this;
	}

	private Field[] getFields() {
		try {
			return getClass().getDeclaredFields();
		} catch (Exception e) {
			return getClass().getFields();
		}
	}

	protected final void init() {
		for (Field field : getFields()) {
			try {
				field.setAccessible(true);
				if (field.isAnnotationPresent(SettingProperty.class)) {
					SettingProperty settingProperty = field
							.getAnnotation(SettingProperty.class);
					if (settingProperty.create()) {
						field.set(this, field.getType().newInstance());
					}
					Property property = (Property) field.get(this);
					property.onSetDefaultValue(settingProperty);
					attach(property);
				}
			} catch (Exception e) {
				Log.e(Setting.TAG, "Error on processing property", e);
			}
		}
		onInit();
	}

	protected void onInit() {

	}

	@SuppressWarnings("unchecked")
	protected void onPropertyChange(Property property) {
		for (SettingListener listener : listeners) {
			try {
				listener.onPropertyChange((T) this, property);
			} catch (RuntimeException e) {
				Log.w(Setting.TAG, "Listener error", e);
			}
		}
	}

	@SuppressWarnings("unchecked")
	public final T removeListener(SettingListener listener) {
		if (listener == null) {
			throw new IllegalArgumentException("SettingListener can't be null");
		}
		if (listeners.contains(listener)) {
			listener.onDetach((T) this);
			listeners.remove(listener);
		}
		return (T) this;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy