package edu.uw.zookeeper; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import edu.uw.zookeeper.common.Application; import edu.uw.zookeeper.common.Builder; import edu.uw.zookeeper.common.ParameterizedFactory; import edu.uw.zookeeper.common.RuntimeModule; public abstract class ZooKeeperApplication implements Application { public static <T extends RuntimeBuilder<? extends Application, ?>> void main(String[] args, T builder) { DefaultMain.main(args, factory(builder)); } public static <T extends RuntimeBuilder<? extends Application, ?>> ApplicationFactory<T> factory(T builder) { return ApplicationFactory.create(builder); } public static interface RuntimeBuilder<T, C extends RuntimeBuilder<T,C>> extends Builder<T> { RuntimeModule getRuntimeModule(); C setRuntimeModule(RuntimeModule runtime); C setDefaults(); } public static abstract class AbstractRuntimeBuilder<T, C extends AbstractRuntimeBuilder<T,C>> implements RuntimeBuilder<T,C> { protected final RuntimeModule runtime; protected AbstractRuntimeBuilder( RuntimeModule runtime) { this.runtime = runtime; } @Override public RuntimeModule getRuntimeModule() { return runtime; } @Override public C setRuntimeModule(RuntimeModule runtime) { return newInstance(runtime); } @SuppressWarnings("unchecked") @Override public C setDefaults() { checkState(getRuntimeModule() != null); return (C) this; } @Override public T build() { return setDefaults().doBuild(); } protected abstract C newInstance(RuntimeModule runtime); protected abstract T doBuild(); } public static class ApplicationFactory<T extends RuntimeBuilder<? extends Application, ?>> implements ParameterizedFactory<RuntimeModule, Application> { public static <T extends RuntimeBuilder<? extends Application, ?>> ApplicationFactory<T> create(T builder) { return new ApplicationFactory<T>(builder); } protected final T builder; public ApplicationFactory(T builder) { this.builder = builder; } @Override public Application get(RuntimeModule runtime) { return builder.setRuntimeModule(runtime).setDefaults().build(); } } public static abstract class ForwardingBuilder<V, T extends RuntimeBuilder<?,?>, C extends ForwardingBuilder<V,T,C>> implements RuntimeBuilder<V,C> { protected final T delegate; public ForwardingBuilder(T delegate) { this.delegate = checkNotNull(delegate); } @Override public RuntimeModule getRuntimeModule() { return delegate.getRuntimeModule(); } @SuppressWarnings("unchecked") @Override public C setRuntimeModule(RuntimeModule runtime) { return newInstance((T) delegate.setRuntimeModule(runtime)); } @SuppressWarnings("unchecked") @Override public C setDefaults() { return newInstance((T) delegate.setDefaults()); } @Override public V build() { return setDefaults().doBuild(); } protected abstract C newInstance(T delegate); protected abstract V doBuild(); } public static class ForwardingApplication implements Application { protected final Runnable delegate; public ForwardingApplication(Runnable delegate) { this.delegate = delegate; } @Override public void run() { delegate.run(); } } protected ZooKeeperApplication() {} }