package sk.stuba.fiit.perconik.core.services;
import com.google.common.base.Preconditions;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* An abstract extension of {@link AbstractService} class holding
* {@link Provider} and {@link Manager} instances. This skeleton
* implementation provides an abstract builder mechanism to construct
* instances of extended classes.
*
* @param <P> the type of the provider for this service
* @param <M> the type of the manager for this service
*
* @author Pavol Zbell
* @since 1.0
*/
public abstract class AbstractGenericService<P extends Provider, M extends Manager> extends AbstractService {
/**
* The provider.
*/
protected final P provider;
/**
* The manager.
*/
protected final M manager;
/**
* Constructor for use by subclasses.
*/
protected AbstractGenericService(final AbstractGenericBuilder<?, P, M> builder) {
this.provider = checkNotNull(builder.provider);
this.manager = checkNotNull(builder.manager);
}
/**
* An abstract builder for creating generic service instances.
*
* <p>Builder instances can be reused, it is safe to call {@link #build}
* multiple times to build multiple generic services in series.
*
* @param <B> the type of the extender of this builder
* @param <P> the type of the provider for the built service
* @param <M> the type of the manager for the built service
*
* @author Pavol Zbell
* @since 1.0
*/
protected static abstract class AbstractGenericBuilder<B extends AbstractGenericBuilder<B, P, M>, P extends Provider, M extends Manager> {
P provider;
M manager;
/**
* Constructor for use by subclasses.
*/
protected AbstractGenericBuilder() {}
/**
* Must always return {@code this}.
*/
protected abstract B asSubtype();
/**
* Sets the provider of the built generic service.
* @param provider the provider, not {@code null}
* @return this {@code Builder} object
* @throws NullPointerException if the provider is {@code null}
* @throws IllegalStateException if the provider is already set
*/
public final B provider(final P provider) {
Preconditions.checkState(this.provider == null);
this.provider = checkNotNull(provider);
return this.asSubtype();
}
/**
* Sets the manager of the built generic service.
* @param manager the provider, not {@code null}
* @return this {@code Builder} object
* @throws NullPointerException if the manager is {@code null}
* @throws IllegalStateException if the manager is already set
*/
public final B manager(final M manager) {
Preconditions.checkState(this.manager == null);
this.manager = checkNotNull(manager);
return this.asSubtype();
}
/**
* Returns a newly created generic service.
*/
public abstract Service build();
}
}