package com.peterhi.almostthere;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.peterhi.almostthere.errors.EventIgnoredException;
final class Property {
private final Class<?> protocol;
private final Object object;
private final String name;
private final Class<?> type;
private final List<Listener> listeners;
private Object value;
private Object collection;
private Method is$Method;
private Method get$Method;
private Method set$Method;
private Method $sMethod;
private Method swap$sImplementationMethod;
private Method add$ListenerMethod;
private Method remove$ListenerMethod;
private Method getAll$ListenersMethod;
private Method removeAll$ListenersMethod;
public Property(Class<?> protocol, Object object, String name, Class<?> type) {
this.protocol = protocol;
this.object = object;
this.name = name;
this.type = type;
this.listeners = new ArrayList<Listener>();
}
public Class<?> getProtocol() {
return protocol;
}
public Object getObject() {
return object;
}
public String getName() {
return name;
}
public Class<?> getType() {
return type;
}
public Object getValue() {
return value;
}
public Object setValue(Object value) {
Object old = this.value;
try {
Object neo = dispatchBeforeSet(null, old, value);
this.value = neo;
dispatchAfterSet(null, old, neo);
} catch (EventIgnoredException ex) {
}
return old;
}
public Object getCollection() {
return collection;
}
public void swapCollection(Object collection) {
this.collection = collection;
}
public void addListener(Listener listener) {
listeners.add(listener);
}
public void removeListener(Listener listener) {
listeners.remove(listener);
}
public Listener[] getAllListeners() {
return listeners.toArray(new Listener[listeners.size()]);
}
public Listener[] removeAllListeners() {
Listener[] allListeners = getAllListeners();
listeners.clear();
return allListeners;
}
public void fireBeforeAdd(Event event) {
for (Listener listener : listeners) {
listener.beforeAdd(event);
}
}
public void fireAfterAdd(Event event) {
for (Listener listener : listeners) {
listener.afterAdd(event);
}
}
public void fireBeforeSet(Event event) {
for (Listener listener : listeners) {
listener.beforeSet(event);
}
}
public void fireAfterSet(Event event) {
for (Listener listener : listeners) {
listener.afterSet(event);
}
}
public void fireBeforeRemove(Event event) {
for (Listener listener : listeners) {
listener.beforeRemove(event);
}
}
public void fireAfterRemove(Event event) {
for (Listener listener : listeners) {
listener.afterRemove(event);
}
}
public Object dispatchBeforeAdd(Object key, Object oldValue, Object newValue) throws EventIgnoredException {
Event event = new Event(object, protocol, name, type, key, oldValue);
event.setNewValue(newValue);
fireBeforeAdd(event);
if (event.isIgnored()) {
throw new EventIgnoredException();
}
return event.getNewValue();
}
public void dispatchAfterAdd(Object key, Object oldValue, Object newValue) {
Event event = new Event(object, protocol, name, type, key, oldValue);
event.setNewValue(newValue);
fireAfterAdd(event);
}
public Object dispatchBeforeSet(Object key, Object oldValue, Object newValue) throws EventIgnoredException {
Event event = new Event(object, protocol, name, type, key, oldValue);
event.setNewValue(newValue);
fireBeforeSet(event);
if (event.isIgnored()) {
throw new EventIgnoredException();
}
return event.getNewValue();
}
public void dispatchAfterSet(Object key, Object oldValue, Object newValue) {
Event event = new Event(object, protocol, name, type, key, oldValue);
event.setNewValue(newValue);
fireAfterSet(event);
}
public Object dispatchBeforeRemove(Object key, Object value) throws EventIgnoredException {
Event event = new Event(object, protocol, name, type, key, value);
event.setNewValue(value);
fireBeforeRemove(event);
if (event.isIgnored()) {
throw new EventIgnoredException();
}
return event.getNewValue();
}
public void dispatchAfterRemove(Object key, Object value) {
Event event = new Event(object, protocol, name, type, key, value);
event.setNewValue(value);
fireAfterRemove(event);
}
public boolean hasIs$Method() {
return is$Method != null;
}
public boolean hasGet$Method() {
return get$Method != null;
}
public boolean hasSet$Method() {
return set$Method != null;
}
public boolean has$sMethod() {
return $sMethod != null;
}
public boolean hasSwap$sImplementationMethod() {
return swap$sImplementationMethod != null;
}
public boolean hasAdd$ListenerMethod() {
return add$ListenerMethod != null;
}
public boolean hasRemove$ListenerMethod() {
return remove$ListenerMethod != null;
}
public boolean hasGetAll$ListenersMethod() {
return getAll$ListenersMethod != null;
}
public boolean hasRemoveAll$ListenersMethod() {
return removeAll$ListenersMethod != null;
}
public Method queryIs$Method() throws NoSuchMethodException {
Method method = protocol.getMethod(MessageFormat.format("is{0}", name));
if (method.getReturnType() != boolean.class) {
throw new NoSuchMethodException(method + " does not return boolean");
}
return method;
}
public Method queryGet$Method() throws NoSuchMethodException {
Method method = protocol.getMethod(MessageFormat.format("get{0}", name));
if (method.getReturnType() != type) {
throw new NoSuchMethodException(method + " does not return " + type);
}
return method;
}
public Method querySet$Method() throws NoSuchMethodException {
Method method = protocol.getMethod(MessageFormat.format("set{0}", name), type);
if (method.getReturnType() != type) {
throw new NoSuchMethodException(method + " does not return " + type);
}
return method;
}
public Method query$sMethod() throws NoSuchMethodException {
Method method = protocol.getMethod(MessageFormat.format("{0}{1}", Character.toLowerCase(name.charAt(0)), name.substring(1)));
if (method.getReturnType() != Set.class &&
method.getReturnType() != List.class &&
method.getReturnType() != Map.class) {
throw new NoSuchMethodException(method + " must return either Set, List or Map");
}
return method;
}
public Method querySwap$sImplementationMethod() throws NoSuchMethodException {
Method method = protocol.getMethod(MessageFormat.format("swap{0}Implementation", name), type);
if (method.getReturnType() != void.class) {
throw new NoSuchMethodException(method + " does not return void");
}
return method;
}
public Method queryAdd$ListenerMethod() throws NoSuchMethodException {
Method method = protocol.getMethod(MessageFormat.format("add{0}Listener", name), Listener.class);
if (method.getReturnType() != void.class) {
throw new NoSuchMethodException(method + " does not return void");
}
return method;
}
public Method queryRemove$ListenerMethod() throws NoSuchMethodException {
Method method = protocol.getMethod(MessageFormat.format("remove{0}Listener", name), Listener.class);
if (method.getReturnType() != void.class) {
throw new NoSuchMethodException(method + " does not return void");
}
return method;
}
public Method queryGetAll$ListenersMethod() throws NoSuchMethodException {
Method method = protocol.getMethod(MessageFormat.format("getAll{0}Listeners", name));
if (method.getReturnType() != Listener[].class) {
throw new NoSuchMethodException(method + " does not return " + Listener[].class);
}
return method;
}
public Method queryRemoveAll$ListenersMethod() throws NoSuchMethodException {
Method method = protocol.getMethod(MessageFormat.format("removeAll{0}Listeners", name));
if (method.getReturnType() != Listener[].class) {
throw new NoSuchMethodException(method + " does not return " + Listener[].class);
}
return method;
}
public boolean tryQueryIs$Method() {
try {
setIs$Method(queryIs$Method());
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public boolean tryQueryGet$Method() {
try {
setGet$Method(queryGet$Method());
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public boolean tryQuerySet$Method() {
try {
setSet$Method(querySet$Method());
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public boolean tryQuery$sMethod() {
try {
set$sMethod(query$sMethod());
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public boolean tryQuerySwap$sImplementationMethod() {
try {
setSwap$sImplementationMethod(querySwap$sImplementationMethod());
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public boolean tryQueryAdd$ListenerMethod() {
try {
setAdd$ListenerMethod(queryAdd$ListenerMethod());
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public boolean tryQueryRemove$ListenerMethod() {
try {
setRemove$ListenerMethod(queryRemove$ListenerMethod());
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public boolean tryQueryGetAll$ListenersMethod() {
try {
setGetAll$ListenersMethod(queryGetAll$ListenersMethod());
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public boolean tryQueryRemoveAll$ListenersMethod() {
try {
setRemoveAll$ListenersMethod(queryRemoveAll$ListenersMethod());
return true;
} catch (NoSuchMethodException ex) {
return false;
}
}
public Method getIs$Method() {
return is$Method;
}
public Method getGet$Method() {
return get$Method;
}
public Method getSet$Method() {
return set$Method;
}
public Method get$sMethod() {
return $sMethod;
}
public Method getSwap$sImplementationMethod() {
return swap$sImplementationMethod;
}
public Method getAdd$ListenerMethod() {
return add$ListenerMethod;
}
public Method getRemove$ListenerMethod() {
return remove$ListenerMethod;
}
public Method getGetAll$ListenersMethod() {
return getAll$ListenersMethod;
}
public Method getRemoveAll$ListenersMethod() {
return removeAll$ListenersMethod;
}
public void setIs$Method(Method value) {
is$Method = value;
}
public void setGet$Method(Method value) {
get$Method = value;
}
public void setSet$Method(Method value) {
set$Method = value;
}
public void set$sMethod(Method value) {
$sMethod = value;
}
public void setSwap$sImplementationMethod(Method value) {
swap$sImplementationMethod = value;
}
public void setAdd$ListenerMethod(Method value) {
add$ListenerMethod = value;
}
public void setRemove$ListenerMethod(Method value) {
remove$ListenerMethod = value;
}
public void setGetAll$ListenersMethod(Method value) {
getAll$ListenersMethod = value;
}
public void setRemoveAll$ListenersMethod(Method value) {
removeAll$ListenersMethod = value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Property other = (Property) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return protocol + "." + name;
}
}