// STACKMedium.java

package protocol;				// protocol package

import java.util.*;				// import Java utility classes

import support.*;				// import Jasper support classes

/**
  This is the class that defines the medium for a protocol stack.

  @author	Kenneth J. Turner
  @version	1.0 (20th July 2010): initial version
*/
public class STACKMedium extends Medium {

  /** Service send offer */
  private final static String SEND =
    "Send medium message to physical layer";

  /** Service provider events */
  private Vector<ProtocolEvent> serviceEvents;

  /** Service data unit input */
  private PDU serviceIn;

  /** Service data unit output */
  private PDU serviceOut;

  /** Service user */
  private ProtocolEntity serviceUser;

  /**
    Constructor for protocol stack medium.
  */
  public STACKMedium() {
    initialise();				// initialise service entity
  }

  /**
    Return services currently offered.

    @return		list of services (empty)
  */
  public Vector<String> getServices() {
    Vector<String> list = new Vector<String>();	// initialise service list
    if (serviceIn != null)			// SDU from medium?
      list.addElement(SEND);			// add send SDU service to list
    return(list);				// return service list
  }

  /**
    Initialise the service entity.
  */
  public void initialise() {
    serviceEvents = new Vector<ProtocolEvent>();// initialise service events
    serviceIn = null;				// initialise SDU input
    serviceOut = null;				// initialise SDU output
  }

  /**
    Perform service.

    @param service	service request
    @return		resulting service events
  */
  public Vector<ProtocolEvent> performService(String service) {
    serviceEvents = new Vector<ProtocolEvent>();// initialise service events
    if (service.startsWith(SEND)) {		// send request?
      String message = serviceIn.getSDU();	// create service message
      PDU sdu = new STACKSdu(message);		// create SDU
      serviceEvents.addElement(			// add send event
	new ProtocolEvent(ProtocolEvent.SEND, sdu));
      transmitPDU(sdu, serviceUser);		// send service message
      serviceIn = null;				// re-initialise SDU in
    }
    return(serviceEvents);			// return service events
  }
  /**
    Receive an SDU.

    @param sdu		SDU
    @return		resulting service events
  */
  public Vector<ProtocolEvent> receivePDU(PDU sdu) {
    serviceIn = sdu;				// store SDU from service
    serviceEvents = new Vector<ProtocolEvent>();// initialise service events
    return(serviceEvents);			// return service events
  }

  /**
    Set the service user.

    @param serviceUser		service user
  */
  public void setUser(ProtocolEntity serviceUser) {
    this.serviceUser = serviceUser;		// set service user
  }

  /**
    Send an SDU.

    @param sdu		SDU
    @param dest		destination protocol entity
  */
  public void transmitPDU(PDU sdu, ProtocolEntity destination) {
    sdu.setSource(this);			// set source as this entity
    sdu.setDestination(destination);		// set destination
    Vector<ProtocolEvent> receiveEvents =	// receive SDU at destination
      destination.receivePDU(sdu);
  }

}

