AbstractServer.java

/*
 * @copyright defined in LICENSE.txt
 */

package hera.server;

import static hera.server.ServerStatus.TERMINATED;
import static hera.util.ValidationUtils.assertNotNull;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.ArrayList;
import lombok.Getter;
import org.slf4j.Logger;

public abstract class AbstractServer implements Server, StateChangeListener<ServerStatus> {

  protected final Logger logger = getLogger(getClass());

  /**
   * server status.
   */
  protected StateMachine<ServerStatus> state = new StateMachine<ServerStatus>(TERMINATED);

  /**
   * server listeners.
   */
  protected ArrayList<ServerListener> listeners = new ArrayList<ServerListener>();

  /**
   * Latest exception.
   */
  @Getter
  protected Throwable exception = null;


  /**
   * Server name for track.
   */
  @Getter
  protected String name = getClass().getSimpleName();

  public AbstractServer() {
    state.addListener(this);
  }

  /* (non-Javadoc)
   * @see Server#getStatus()
   */
  @Override
  public ServerStatus getStatus() {
    return state.getState();
  }

  /* (non-Javadoc)
   * @see Server#isStatus(ServerStatus[])
   */
  @Override
  public boolean isStatus(final ServerStatus... status) {
    return state.isState(status);
  }

  /* (non-Javadoc)
   * @see Server#waitStatus(ServerStatus[])
   */
  @Override
  public void waitStatus(final ServerStatus... status) {
    state.waitState(status);
  }


  /**
   * Change status to {@code status}.
   *
   * @param status status to set
   */
  protected void changeStatus(final ServerStatus status) {
    state.changeState(status);
  }

  @Override
  public void stateChanged(final ServerStatus old, final ServerStatus state, final Object... args) {
    fireEvent(new ServerEvent(this, STATUS_CHANGED, old, state));
  }

  /**
   * Clear exception.
   */
  public void clearException() {
    this.exception = null;
  }


  /* (non-Javadoc)
   * @see Server#addServerListener(ServerListener)
   */
  @Override
  public void addServerListener(final ServerListener listener) {
    assertNotNull(listener);
    this.listeners.add(listener);
  }

  /* (non-Javadoc)
   * @see Server#removeServerListener(ServerListener)
   */
  @Override
  public void removeServerListener(final ServerListener listener) {
    this.listeners.remove(listener);
  }


  /**
   * Fire {@link ServerEvent} {@code e} to listeners.
   *
   * @param event {@link ServerEvent} to fire
   */
  protected void fireEvent(final ServerEvent event) {
    for (final ServerListener listener : this.listeners) {
      listener.handle(event);
    }
    if (listeners.isEmpty()) {
      logger.trace("Event[{}] is discarded", event);
    } else {
      logger.info("Event[{}] is fired to {} listeners", event, listeners.size());
    }
  }

  /**
   * Initialization part.
   *
   * @throws Exception Fail to initialize the server
   */
  protected void initialize() throws Exception {
  }

  /**
   * Process part.
   *
   * @throws Exception Fail to process the server task
   */
  protected void process() throws Exception {
  }

  /**
   * Exception handling part in process.
   *
   * @param th exception to be occurred
   */
  protected void handleError(final Throwable th) {
    throw new IllegalStateException(th);
  }

  /**
   * Post process part.
   * <p>
   * No exception occurred
   *
   * Just one called though exception occurred
   * </p>
   */
  protected void terminate() {
  }

}