package fr.openwide.core.wicket.more.markup.html.basic.impl;
import java.util.Collection;
import java.util.List;
import org.apache.wicket.Component;
import org.apache.wicket.injection.Injector;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import fr.openwide.core.commons.util.functional.Predicates2;
import fr.openwide.core.wicket.more.condition.BooleanOperator;
import fr.openwide.core.wicket.more.condition.Condition;
import fr.openwide.core.wicket.more.markup.html.basic.AbstractComponentBooleanPropertyBehavior;
import fr.openwide.core.wicket.more.markup.html.basic.ComponentBooleanProperty;
import fr.openwide.core.wicket.more.markup.html.basic.IPlaceholderEnclosureBuilder;
public abstract class AbstractConfigurableComponentBooleanPropertyBehavior<T extends AbstractConfigurableComponentBooleanPropertyBehavior<T>>
extends AbstractComponentBooleanPropertyBehavior
implements IPlaceholderEnclosureBuilder<T> {
private static final long serialVersionUID = 5054905572454226562L;
private static final IModel<?> NULL_MODEL = new AbstractReadOnlyModel<Object>() {
private static final long serialVersionUID = 1L;
@Override
public Object getObject() {
return null;
}
};
public static enum Operator {
WHEN_ALL_TRUE(BooleanOperator.AND),
WHEN_ANY_TRUE(BooleanOperator.OR),
WHEN_ALL_FALSE(BooleanOperator.NOR),
WHEN_ANY_FALSE(BooleanOperator.NAND);
private final BooleanOperator booleanOperator;
private Operator(BooleanOperator booleanOperator) {
this.booleanOperator = booleanOperator;
}
public BooleanOperator getBooleanOperator() {
return booleanOperator;
}
}
private final BooleanOperator operator;
private final List<Condition> conditions = Lists.newArrayList();
protected AbstractConfigurableComponentBooleanPropertyBehavior(ComponentBooleanProperty property, Operator operator) {
this(property, operator.getBooleanOperator());
}
private AbstractConfigurableComponentBooleanPropertyBehavior(ComponentBooleanProperty property, BooleanOperator operator) {
super(property);
this.operator = operator;
Injector.get().inject(this);
}
@Override
protected boolean generatePropertyValue(Component attachedComponent) {
return operator.apply(conditions);
}
/**
* @return this as an object of type T
* @see PlaceholderBehavior
* @see EnclosureBehavior
*/
protected abstract T thisAsT();
@Override
public T model(IModel<?> model) {
return model(Predicates.notNull(), model);
}
@Override
public T collectionModel(IModel<? extends Collection<?>> model) {
return model(Predicates2.notEmpty(), model);
}
@Override
@SuppressWarnings("unchecked")
public <T2> T model(Predicate<? super T2> predicate, IModel<? extends T2> model) {
conditions.add(Condition.predicate(model == null ? (IModel<? extends T2>) NULL_MODEL : model, predicate));
return thisAsT();
}
@Override
public T models(IModel<?> firstModel, IModel<?>... otherModels) {
for (IModel<?> model : Lists.asList(firstModel, otherModels)) {
model(model);
}
return thisAsT();
}
@Override
@SafeVarargs
public final <T2> T models(Predicate<? super T2> predicate, IModel<? extends T2> firstModel,
IModel<? extends T2>... otherModels) {
for (IModel<? extends T2> model : Lists.asList(firstModel, otherModels)) {
model(predicate, model);
}
return thisAsT();
}
@Override
public T component(Component component) {
conditions.add(Condition.visible(component));
return thisAsT();
}
@Override
public T components(Component firstComponent, Component... otherComponents) {
return components(Lists.asList(firstComponent, otherComponents));
}
@Override
public T components(Collection<? extends Component> targetComponents) {
for (Component component : targetComponents) {
conditions.add(Condition.visible(component));
}
return thisAsT();
}
public T condition(Condition condition) {
conditions.add(condition);
return thisAsT();
}
@Override
public void detach(Component component) {
super.detach(component);
for (Condition condition : conditions) {
condition.detach();
}
}
}