package xapi.inject.impl; import xapi.util.api.MergesValues; /** * A default object designed to convert two values into one value. * <br> * The {@link #create(K1, K2)} method is provided to initializes the value. * If you use a constructor that accepts another {@link MergesValues}, * that delegate will only be called to create the value object. * If you override the create method, it will be called until it returns non null. * <br> * If you want to perform some initialization on every call to {@link #merge(K1, K2)}, * you should override the {@link #refresh(K1, K2, V)} method. * <br> * Care should be taken to only perform idempotent actions inside the refresh method, * as implementations are free to assume it is safe (and performant) to call refresh many times. * * @author "James X. Nelson (james@wetheinter.net)" * * @param <K1> * @param <K2> * @param <V> */ public class LazyMerger <K1, K2, V> implements MergesValues<K1, K2, V> { public LazyMerger() { } public LazyMerger(MergesValues<K1, K2, V> merger) { this.delegate = merger; } public LazyMerger(MergesValues<K1, K2, V> merger, V value) { this.delegate = merger; this.value = value; } public LazyMerger(V value) { this.value = value; } MergesValues<K1, K2, V> delegate; V value; @Override public final V merge(K1 k1, K2 k2) { if (value == null) { value = create(k1, k2); if (value != null) { refresh(k1, k2, value); } } else { refresh(k1, k2, value); } return value; } /** * Default action is to do nothing. * <br/> * This method is provided so you can fill in actions that should be taken * on the value result, (only called when the value is not null). */ protected void refresh(K1 k1, K2 k2, V value) { } protected V create(K1 k1, K2 k2) { return delegate == null ? null : delegate.merge(k1, k2); } }