package fr.openwide.core.wicket.more.link.descriptor.builder.impl.parameter;
import java.util.Collections;
import java.util.List;
import org.apache.wicket.model.IDetachable;
import org.bindgen.BindingRoot;
import org.bindgen.binding.AbstractBinding;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import fr.openwide.core.wicket.more.link.descriptor.builder.impl.parameter.mapping.CollectionLinkParameterMappingEntry;
import fr.openwide.core.wicket.more.link.descriptor.builder.impl.parameter.mapping.SimpleLinkParameterMappingEntry;
import fr.openwide.core.wicket.more.link.descriptor.builder.state.parameter.chosen.ITwoMappableParameterOneChosenParameterState;
import fr.openwide.core.wicket.more.link.descriptor.builder.state.parameter.chosen.ITwoMappableParameterTwoChosenParameterState;
import fr.openwide.core.wicket.more.link.descriptor.builder.state.parameter.chosen.common.IChosenParameterState;
import fr.openwide.core.wicket.more.link.descriptor.builder.state.parameter.chosen.common.IOneChosenParameterState;
import fr.openwide.core.wicket.more.link.descriptor.builder.state.parameter.mapping.IAddedParameterMappingState;
import fr.openwide.core.wicket.more.link.descriptor.parameter.mapping.InjectOnlyLinkParameterMappingEntry;
import fr.openwide.core.wicket.more.link.descriptor.parameter.mapping.factory.ILinkParameterMappingEntryFactory;
import fr.openwide.core.wicket.more.link.descriptor.parameter.validator.ConditionLinkParameterValidator;
import fr.openwide.core.wicket.more.link.descriptor.parameter.validator.factory.ILinkParameterValidatorFactory;
import fr.openwide.core.wicket.more.markup.html.factory.IDetachableFactory;
/**
* A base for implementing all interfaces that extend {@link IChosenParameterState}.
*
* <p>In order to keep things simple, it is expected that multiple interfaces are implemented at once. For example,
* the implementation for two available parameters will implement {@link ITwoMappableParameterOneChosenParameterState}
* <strong>and</strong> {@link ITwoMappableParameterTwoChosenParameterState}. This implies that generics must be left aside
* (we use raw types).
*/
@SuppressWarnings("rawtypes")
public abstract class AbstractChosenParameterStateImpl<TSelf, TInitialState>
implements IChosenParameterState, IOneChosenParameterState {
private final List<Integer> parameterIndices;
public AbstractChosenParameterStateImpl() {
this.parameterIndices = Lists.newArrayList();
}
protected abstract LinkParameterTypeInformation<?> getParameterTypeInformation(int index);
public List<Integer> getParameterIndices() {
return Collections.unmodifiableList(parameterIndices);
}
private void addDynamicParameter(int index) {
parameterIndices.add(index);
}
private int getFirstIndex() {
return parameterIndices.get(0);
}
@Override
@SuppressWarnings("unchecked")
public IAddedParameterMappingState<TInitialState> map(String parameterName) {
LinkParameterTypeInformation<?> typeInfo = getParameterTypeInformation(getFirstIndex());
if (typeInfo.getTypeDescriptorSupplier().get().isCollection()) {
return map(CollectionLinkParameterMappingEntry.factory(
parameterName, typeInfo.getTypeDescriptorSupplier(), (Supplier) typeInfo.getEmptyValueSupplier()
));
} else {
return map(SimpleLinkParameterMappingEntry.factory(
parameterName, typeInfo.getTypeDescriptorSupplier()
));
}
}
@Override
public abstract IAddedParameterMappingState<TInitialState> map(ILinkParameterMappingEntryFactory parameterMappingEntryFactory);
@Override
public IAddedParameterMappingState<TInitialState> renderInUrl(String parameterName) {
return map(InjectOnlyLinkParameterMappingEntry.factory(parameterName));
}
@SuppressWarnings("unchecked")
@Override
public IAddedParameterMappingState<TInitialState> renderInUrl(String parameterName, AbstractBinding binding) {
return map(InjectOnlyLinkParameterMappingEntry.factory(parameterName, binding));
}
@SuppressWarnings("unchecked")
@Override
public TInitialState validator(Predicate predicate) {
// (ILinkParameterValidatorFactory) cast to raw-type needed in java 8
return validator((ILinkParameterValidatorFactory) ConditionLinkParameterValidator.predicateFactory(predicate));
}
@Override
public TInitialState permission(String permissionName) {
return validator(ConditionLinkParameterValidator.anyPermissionFactory(ImmutableList.of(permissionName)));
}
@Override
public TInitialState permission(String firstPermissionName, String... otherPermissionNames) {
return validator(ConditionLinkParameterValidator.anyPermissionFactory(Lists.asList(firstPermissionName, otherPermissionNames)));
}
@SuppressWarnings("unchecked")
@Override
public TInitialState permission(BindingRoot binding, String firstPermissionName,
String... otherPermissionNames) {
// (ILinkParameterValidatorFactory) cast to raw-type needed in java 8
return validator((ILinkParameterValidatorFactory) ConditionLinkParameterValidator.anyPermissionFactory(binding,
Lists.asList(firstPermissionName, otherPermissionNames)));
}
@Override
public abstract TInitialState validator(ILinkParameterValidatorFactory parameterValidatorFactory);
@SuppressWarnings("unchecked")
@Override
public TInitialState validator(IDetachableFactory conditionFactory) {
// (ILinkParameterValidatorFactory) cast to raw-type needed in java 8
return validator((ILinkParameterValidatorFactory) ConditionLinkParameterValidator.fromConditionFactory(conditionFactory));
}
@Override
public abstract IDetachable page(IDetachableFactory pageClassFactory);
@Override
public abstract IDetachable resource(IDetachableFactory resourceReferenceFactory);
@Override
public abstract IDetachable imageResource(IDetachableFactory resourceReferenceFactory);
protected abstract TSelf thisAsTSelf();
public TSelf andFirst() {
addDynamicParameter(0);
return thisAsTSelf();
}
public TSelf andSecond() {
addDynamicParameter(1);
return thisAsTSelf();
}
public TSelf andThird() {
addDynamicParameter(2);
return thisAsTSelf();
}
public TSelf andFourth() {
addDynamicParameter(3);
return thisAsTSelf();
}
}