package fr.openwide.core.wicket.more.markup.html.bootstrap.label.renderer;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Locale;
import java.util.Objects;
import org.apache.wicket.model.IModel;
import fr.openwide.core.wicket.more.markup.html.bootstrap.label.model.IBootstrapColor;
import fr.openwide.core.wicket.more.model.LocaleAwareReadOnlyModel;
import fr.openwide.core.wicket.more.rendering.Renderer;
import fr.openwide.core.wicket.more.util.model.Detachables;
public abstract class BootstrapRenderer<T> extends Renderer<T> {
private static final long serialVersionUID = -715674989551497434L;
public static <T> BootstrapRenderer<T> constant(final String resourceKey, final String icon, final IBootstrapColor color) {
return constant(resourceKey, resourceKey, icon, color);
}
public static <T> BootstrapRenderer<T> constant(final String labelResourceKey, final String tooltipResourceKey, final String icon, final IBootstrapColor color) {
return new BootstrapRenderer<T>() {
private static final long serialVersionUID = 1L;
@Override
protected BootstrapRendererInformation doRender(T value, Locale locale) {
return BootstrapRendererInformation.builder()
.label(getString(labelResourceKey, locale))
.tooltip(getString(tooltipResourceKey, locale))
.icon(icon)
.color(color)
.build();
}
};
}
public BootstrapRenderer() {
super();
}
protected abstract BootstrapRendererInformation doRender(T value, Locale locale);
@Override
public String render(T value, Locale locale) {
BootstrapRendererInformation information = doRender(value, locale);
return information == null ? null : information.getLabel();
}
public IBootstrapColor renderColor(T value, Locale locale) {
BootstrapRendererInformation information = doRender(value, locale);
return information == null ? null : information.getColor();
}
public String renderIconCssClass(T value, Locale locale) {
BootstrapRendererInformation information = doRender(value, locale);
return information == null ? null : information.getIconCssClass();
}
public String renderTooltip(T value, Locale locale) {
BootstrapRendererInformation information = doRender(value, locale);
return information == null ? null : information.getTooltip();
}
@Override
public IBootstrapRendererModel asModel(IModel<? extends T> valueModel) {
return new BootstrapRendererModel(valueModel);
}
private final class BootstrapRendererModel extends LocaleAwareReadOnlyModel<String>
implements IBootstrapRendererModel {
private static final long serialVersionUID = -1080017215611311157L;
private final IModel<? extends T> valueModel;
/** Cache the BootstrapInformation so as not to render it three times for each BootstrapLabel
*/
private transient BootstrapRendererInformation lastInformation;
private transient Locale lastLocale;
private transient T lastValue;
public BootstrapRendererModel(IModel<? extends T> valueModel) {
super();
this.valueModel = checkNotNull(valueModel);
}
@Override
public String getObject(Locale locale) {
BootstrapRendererInformation information = getInformation(locale);
return information == null ? null : information.getLabel();
}
@Override
public IModel<String> getIconCssClassModel() {
return new LocaleAwareReadOnlyModel<String>() {
private static final long serialVersionUID = 1L;
@Override
public String getObject(Locale locale) {
BootstrapRendererInformation information = getInformation(locale);
return information == null ? null : information.getIconCssClass();
}
@Override
public void detach() {
super.detach();
BootstrapRendererModel.this.detach();
}
};
}
@Override
public IModel<IBootstrapColor> getColorModel() {
return new LocaleAwareReadOnlyModel<IBootstrapColor>() {
private static final long serialVersionUID = 1L;
@Override
public IBootstrapColor getObject(Locale locale) {
BootstrapRendererInformation information = getInformation(locale);
return information == null ? null : information.getColor();
}
@Override
public void detach() {
super.detach();
BootstrapRendererModel.this.detach();
}
};
}
@Override
public IModel<String> getTooltipModel() {
return new LocaleAwareReadOnlyModel<String>() {
private static final long serialVersionUID = 1L;
@Override
public String getObject(Locale locale) {
BootstrapRendererInformation information = getInformation(locale);
return information == null ? null : information.getTooltip();
}
@Override
public void detach() {
super.detach();
BootstrapRendererModel.this.detach();
}
};
}
private BootstrapRendererInformation getInformation(Locale locale) {
T value = valueModel.getObject();
if (lastInformation != null && Objects.equals(locale, lastLocale) && Objects.equals(value, lastValue)) {
// Use the cache
return lastInformation;
} else {
lastInformation = doRender(value, locale);
lastLocale = locale;
lastValue = value;
return lastInformation;
}
}
@Override
public void detach() {
super.detach();
Detachables.detach(valueModel);
/* Force re-rendering, even if no serialization/deserialization occurs (which would make
* these transient fields null anyway)
*/
lastInformation = null;
lastLocale = null;
lastValue = null;
}
}
}