Package net.sourceforge.javautil.lifecycle.impl

Source Code of net.sourceforge.javautil.lifecycle.impl.LifecycleAbstract

package net.sourceforge.javautil.lifecycle.impl;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import net.sourceforge.javautil.common.event.IEventPropagator;
import net.sourceforge.javautil.common.event.EventProxy;
import net.sourceforge.javautil.common.proxy.CollectionTargetProxy;
import net.sourceforge.javautil.common.shutdown.Shutdown;
import net.sourceforge.javautil.lifecycle.ILifecycle;
import net.sourceforge.javautil.lifecycle.LifecycleEvent;
import net.sourceforge.javautil.lifecycle.LifecycleException;
import net.sourceforge.javautil.lifecycle.ILifecycleListener;
import net.sourceforge.javautil.lifecycle.ILifecyclePhase;
import net.sourceforge.javautil.lifecycle.LifecyclePhaseException;
import net.sourceforge.javautil.lifecycle.ILifecycle.PhaseType;
import net.sourceforge.javautil.lifecycle.LifecycleEvent.TransitionType;

/**
* A standard starting point for most implementations.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public abstract class LifecycleAbstract<T> implements ILifecycle<T> {

  protected final T managed;
 
  protected final IEventPropagator<LifecycleEvent, ILifecycleListener>
    propagator = EventProxy.createProxy(ILifecycleListener.class, LifecycleEvent.class);
 
  protected PhaseType current = PhaseType.INSTANTIATED;
 
  protected ILifecyclePhase<T> from = null;
  protected PhaseType target = null;

  public LifecycleAbstract(T managed) {
    this.managed = managed;
  }

  public synchronized void create() {
    if (this.target == null) this.target = PhaseType.CREATE;
   
    if (this.current == PhaseType.INSTANTIATED) {
      ILifecyclePhase<T> init = this.getPhase(PhaseType.INITIALIZE);
      if (init != null) this.execute(init); else this.fireBefore(PhaseType.INITIALIZE);
     
      this.current = PhaseType.INITIALIZE;
     
      if (init == null) this.fireAfter(PhaseType.INITIALIZE);
    }
   
    if (this.current == PhaseType.INITIALIZE) {
      ILifecyclePhase<T> create = this.getPhase(PhaseType.CREATE);
      if (create != null) this.execute(create); else this.fireBefore(PhaseType.CREATE);
     
      this.current = PhaseType.CREATE;
     
      if (create == null) this.fireAfter(PhaseType.CREATE);
    } else {
      throw new LifecycleException("Not in correct phase for creation: " + this.current, this);
    }
   
    this.target = null;
  }

  public synchronized void start() {
    this.target = PhaseType.START;
   
    if (this.current == PhaseType.INSTANTIATED) this.create();
   
    if (this.current == PhaseType.CREATE || this.current == PhaseType.STOP) {
      List<ILifecyclePhase<T>> prestart = this.getPhases(PhaseType.PRESTART);
      if (prestart.size() > 0) this.execute(prestart); else this.fireBefore(PhaseType.PRESTART);
     
      this.current = PhaseType.PRESTART;
     
      if (prestart.size() == 0) this.fireAfter(PhaseType.PRESTART);
    }
   
    if (this.current == PhaseType.PRESTART) {
      ILifecyclePhase<T> start = this.getPhase(PhaseType.START);
      if (start != null) this.execute(start); else this.fireBefore(PhaseType.START);
     
      this.current = PhaseType.START;
     
      if (start == null) this.fireAfter(PhaseType.START);
    } else {
      throw new LifecycleException("Not in correct phase for starting: " + this.current, this);
    }
   
    this.target = null;
  }

  public synchronized void stop() {
    if (this.current == PhaseType.START) {
      this.target = PhaseType.STOP;
     
      ILifecyclePhase<T> stop = this.getPhase(PhaseType.STOP);
      if (stop != null) this.execute(stop); else this.fireBefore(PhaseType.STOP);
     
      this.current = PhaseType.STOP;

      if (stop == null) this.fireAfter(PhaseType.STOP);
     
      this.target = null;
    } else {
      throw new LifecycleException("Not in correct phase for stopping: " + this.current, this);
    }
  }

  public synchronized void destroy() {
    this.target = PhaseType.DESTROY;
   
    if (this.current == PhaseType.START) this.stop();

    if (this.current == PhaseType.STOP) {
      List<ILifecyclePhase<T>> poststop = this.getPhases(PhaseType.POSTSTOP);
      if (poststop.size() > 0) this.execute(poststop); this.fireBefore(PhaseType.POSTSTOP);
     
      this.current = PhaseType.POSTSTOP;
     
      if (poststop.size() == 0) this.fireAfter(PhaseType.POSTSTOP);
    }
   
    if (this.current == PhaseType.POSTSTOP || this.current == PhaseType.CREATE) {
      ILifecyclePhase<T> destroy = this.getPhase(PhaseType.DESTROY);
      if (destroy != null) this.execute(destroy); this.fireBefore(PhaseType.DESTROY);
     
      this.current = PhaseType.DESTROY;
     
      if (destroy == null) this.fireAfter(PhaseType.DESTROY);
     
      this.target = null;
    } else {
      throw new LifecycleException("Not in correct phase for destroying: " + this.current, this);
    }
  }

  public PhaseType getCurrentPhase() { return this.current; }

  public T getManaged() { return this.managed; }
 
  public void addListener(ILifecycleListener listener) { this.propagator.addListener(listener); }

  public void removeListener(ILifecycleListener listener) { this.propagator.removeListener(listener); }

  public void addListener(Object listener) { this.propagator.addListener(listener); }

  public void removeListener(Object listener) { this.propagator.removeListener(listener); }
 
  public synchronized void shutdown() { this.destroy(); }

  public synchronized boolean isPartialState() { return this.target != null; }

  public synchronized void continueLifecycle () {
    if (this.target == null) return;
   
    if (this.current != this.target) {
      switch (this.target) {
        case CREATE: this.create(); break;
        case DESTROY: this.destroy(); break;
        case START: this.start(); break;
        case STOP: this.stop(); break;
        default:
          throw new LifecycleException("Could not continue lifecycle from failure", this);
      }
    }
  }
 
  /**
   * @param phases The phases to execute
   */
  protected void execute (List<ILifecyclePhase<T>> phases) {
    int start = 0;
    if (this.from != null) start = phases.indexOf(this.from);
    for (int p=start; p<phases.size(); p++) {
      this.execute(phases.get(p));
    }
  }
 
  /**
   * @param phase The phase to execute
   */
  protected void execute (ILifecyclePhase<T> phase) {
    this.fireBefore(phase.getType());
    try {
      this.from = phase;
      phase.execute(this.managed);
      this.from = null;
    } catch (Exception e) {
      phase.rollback(this.managed);
      this.fireFailure(phase.getType());
      throw new LifecyclePhaseException(e, this, phase);
    }
    this.fireAfter(phase.getType());
  }
 
  protected void fireBefore (PhaseType type) {
    ((ILifecycleListener)this.propagator).before(new LifecycleEvent("before", this, type, TransitionType.Before));
  }
 
  protected void fireAfter (PhaseType type) {
    ((ILifecycleListener)this.propagator).after(new LifecycleEvent("after", this, type, TransitionType.After));
  }
 
  protected void fireFailure (PhaseType type) {
    ((ILifecycleListener)this.propagator).failure(new LifecycleEvent("exception", this, type, TransitionType.Failure));
  }
 
  /**
   * @param type The type of phase
   * @return The first phase for the specified type, or null if no such phase is available
   */
  protected abstract ILifecyclePhase<T> getPhase (PhaseType type);
 
  /**
   * @param type The type of phase
   * @return A list, possibly empty, of phases corresponding to the type
   */
  protected abstract List<ILifecyclePhase<T>> getPhases (PhaseType type);
 
}
TOP

Related Classes of net.sourceforge.javautil.lifecycle.impl.LifecycleAbstract

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.