package fr.openwide.core.wicket.more.link.descriptor.builder.impl.factory;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.wicket.model.IModel;
import org.javatuples.Pair;
import org.javatuples.Quartet;
import org.javatuples.Triplet;
import org.javatuples.Tuple;
import org.javatuples.Unit;
import com.google.common.collect.Lists;
import fr.openwide.core.wicket.more.link.descriptor.builder.impl.parameter.LinkParameterMappingEntryBuilder;
import fr.openwide.core.wicket.more.link.descriptor.parameter.mapping.ILinkParameterMappingEntry;
import fr.openwide.core.wicket.more.link.descriptor.parameter.validator.ILinkParameterValidator;
import fr.openwide.core.wicket.more.link.descriptor.parameter.validator.factory.ILinkParameterValidatorFactory;
import fr.openwide.core.wicket.more.markup.html.factory.IDetachableFactory;
import fr.openwide.core.wicket.more.util.model.Detachables;
public final class BuilderMapperLinkDescriptorFactory<TTarget, TLinkDescriptor>
implements IBuilderMapperLinkDescriptorFactory<TLinkDescriptor> {
private static final long serialVersionUID = 4728523709380372544L;
private final IBuilderLinkDescriptorFactory<TTarget, TLinkDescriptor> linkDescriptorFactory;
private final Pair<
? extends IDetachableFactory<? extends Tuple, ? extends IModel<? extends TTarget>>,
? extends List<Integer>
> targetFactory;
private final Map<LinkParameterMappingEntryBuilder<?>, List<Integer>> mappingEntryBuilders;
private final Map<ILinkParameterValidatorFactory<?>, List<Integer>> validatorFactories;
public BuilderMapperLinkDescriptorFactory(
IBuilderLinkDescriptorFactory<TTarget, TLinkDescriptor> linkDescriptorFactory,
Pair<
? extends IDetachableFactory<? extends Tuple, ? extends IModel<? extends TTarget>>,
? extends List<Integer>
> targetFactory,
Map<LinkParameterMappingEntryBuilder<?>, List<Integer>> mappingEntryBuilders,
Map<ILinkParameterValidatorFactory<?>, List<Integer>> validatorFactories) {
super();
this.linkDescriptorFactory = linkDescriptorFactory;
this.targetFactory = targetFactory;
this.mappingEntryBuilders = mappingEntryBuilders;
this.validatorFactories = validatorFactories;
}
private static Tuple extractParameters(Tuple parameters, List<Integer> indices) {
int size = indices.size();
switch (size) {
case 0:
return null;
case 1:
return Unit.with(parameters.getValue(indices.get(0)));
case 2:
return Pair.with(
parameters.getValue(indices.get(0)),
parameters.getValue(indices.get(1))
);
case 3:
return Triplet.with(
parameters.getValue(indices.get(0)),
parameters.getValue(indices.get(1)),
parameters.getValue(indices.get(2))
);
case 4:
return Quartet.with(
parameters.getValue(indices.get(0)),
parameters.getValue(indices.get(1)),
parameters.getValue(indices.get(2)),
parameters.getValue(indices.get(3))
);
default:
throw new IllegalStateException("Only Unit, Pair, Triplet and Quartet parameters are supported for ILinkParameterMappingEntryFactory");
}
}
@Override
public final TLinkDescriptor create(Tuple parameters) {
Collection<ILinkParameterMappingEntry> addedParameterMappingEntries = Lists.newArrayList();
Collection<ILinkParameterValidator> addedValidators = Lists.newArrayList();
IModel<? extends TTarget> target = doCreate(targetFactory.getValue0(), parameters, targetFactory.getValue1());
for (Map.Entry<LinkParameterMappingEntryBuilder<?>, List<Integer>> entry : mappingEntryBuilders.entrySet()) {
List<Integer> indices = entry.getValue();
Pair<ILinkParameterMappingEntry, Collection<ILinkParameterValidator>> result =
doCreate(entry.getKey(), parameters, indices);
addedParameterMappingEntries.add(result.getValue0());
addedValidators.addAll(result.getValue1());
}
for (Map.Entry<ILinkParameterValidatorFactory<?>, List<Integer>> entry : validatorFactories.entrySet()) {
List<Integer> indices = entry.getValue();
ILinkParameterValidator result = doCreate(entry.getKey(), parameters, indices);
addedValidators.add(result);
}
return linkDescriptorFactory.create(target, addedParameterMappingEntries, addedValidators);
}
private static <T extends Tuple, R> R doCreate(IDetachableFactory<T, R> factory, Tuple parameters, List<Integer> indices) {
@SuppressWarnings("unchecked")
IDetachableFactory<Tuple, R> factoryFromTuple = ((IDetachableFactory<Tuple, R>)factory);
Tuple parametersAsTuple = extractParameters(parameters, indices);
return factoryFromTuple.create(parametersAsTuple);
}
@Override
public void detach() {
targetFactory.getValue0().detach();
linkDescriptorFactory.detach();
Detachables.detach(mappingEntryBuilders.keySet());
Detachables.detach(validatorFactories.keySet());
}
}