package org.nocket.gen.page.element.synchronizer;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.wicket.Component;
import org.apache.wicket.feedback.FeedbackMessage;
import org.apache.wicket.feedback.FeedbackMessages;
// TODO: Auto-generated Javadoc
/**
* The Class StateStandard.
*
* @param <E> the element type
*/
@SuppressWarnings("serial")
public class StateStandard<E> implements State<E> {
/** The getter. */
E getter;
/** The choicer. */
Object[] choicer;
/** The enabled. */
boolean enabled;
/** The feedback messages. */
private final Collection<String> feedbackMessages;
/** The touched listener model wrapper. */
private TouchedListenerModelWrapper<E> touchedListenerModelWrapper;
/**
* Instantiates a new state standard.
*
* @param touchedListenerModelWrapper the touched listener model wrapper
* @param component the component
* @param helper the helper
*/
@SuppressWarnings("unchecked")
public StateStandard(TouchedListenerModelWrapper<E> touchedListenerModelWrapper, Component component,
SynchronizerHelper helper) {
this.touchedListenerModelWrapper = touchedListenerModelWrapper;
feedbackMessages = component != null ? feedbackMessageToStringList(component.getFeedbackMessages()) : null;
enabled = helper.isEnabled();
if (helper.getChoicerMethod() != null) {
try {
choicer = pimpArray(helper.invokeChoicer());
} catch (Exception e) {
// during invocation an exception could be, it doesn't matter here
choicer = null;
}
}
if (helper.getGetterMethod() != null) {
try {
getter = (E) helper.invokeGetterMethod();
getter = pimpCollections(getter);
} catch (Exception e) {
// during invocation an exception could be, it doesn't matter here
getter = null;
}
}
}
/**
* Wenn es eine Collection ist, dann nutzt es nicht sich den Wert zu holfen,
* da es nunmal eine Referenz ist. Also muss diese Collection geclont
* werden. Der Rest, sprich der Inhalt der Collection interessiert nicht.
*
* @param object the object
* @return the e
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private E pimpCollections(E object) {
if (object instanceof Collection) {
return (E) pimpCollection((Collection) object);
} else if (object instanceof Object[]) {
return (E) pimpArray((Object[]) object);
}
return object;
}
/**
* Pimp array.
*
* @param <T> the generic type
* @param object the object
* @return the t[]
*/
@SuppressWarnings({ "unchecked" })
private <T> T[] pimpArray(T[] object) {
Class<? extends T[]> newType = (Class<? extends T[]>) object.getClass();
T[] copy = ((Object) newType == (Object) Object[].class)
? (T[]) new Object[object.length]
: (T[]) Array.newInstance(newType.getComponentType(), object.length);
for (int i = 0; i < object.length; i++) {
copy[i] = object[i];
}
return copy;
}
/**
* Pimp collection.
*
* @param oldCollection the old collection
* @return the collection
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
protected Collection pimpCollection(Collection oldCollection) {
Collection newCollection;
try {
newCollection = oldCollection.getClass().newInstance();
newCollection.addAll(oldCollection);
return newCollection;
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((choicer == null) ? 0 : choicer.hashCode());
result = prime * result + (enabled ? 1 : 0);
result = prime * result + ((feedbackMessages == null) ? 0 : feedbackMessages.hashCode());
result = prime * result + ((getter == null) ? 0 : getter.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
@SuppressWarnings("unchecked")
StateStandard<E> other = (StateStandard<E>) obj;
if (!getOuterType().equals(other.getOuterType())) {
return false;
}
boolean hasError = feedbackMessages != null && !feedbackMessages.isEmpty();
boolean otherHasError = other.feedbackMessages != null && !other.feedbackMessages.isEmpty();
if ((hasError && !otherHasError) || (!hasError && otherHasError)) {
return false;
}
if (hasError) {
return CollectionUtils.isEqualCollection(feedbackMessages, other.feedbackMessages);
}
if (choicer == null) {
if (other.choicer != null) {
return false;
}
} else {
if (!ArrayUtils.isEquals(choicer, other.choicer)) {
return false;
}
}
if (enabled != other.enabled) {
return false;
}
if (getter == null) {
if (other.getter != null) {
return false;
}
} else if (!getOuterType().modelUnchanged(other.getter, this.getter)) {
return false;
}
return true;
}
/**
* Feedback message to string list.
*
* @param feedbackMessages the feedback messages
* @return the collection
*/
private Collection<String> feedbackMessageToStringList(FeedbackMessages feedbackMessages) {
ArrayList<String> result = new ArrayList<String>();
for (FeedbackMessage feedbackMessage : feedbackMessages) {
result.add(feedbackMessage.toString());
}
return result;
}
/**
* Gets the outer type.
*
* @return the outer type
*/
private TouchedListenerModelWrapper<E> getOuterType() {
return touchedListenerModelWrapper;
}
}