Package desmoj.extensions.verkettung

Source Code of desmoj.extensions.verkettung.Merger$MergerStartEvent

package desmoj.extensions.verkettung;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import desmoj.core.dist.NumericalDist;
import desmoj.core.simulator.Entity;
import desmoj.core.simulator.Event;
import desmoj.core.simulator.Model;
import desmoj.core.simulator.Queue;
import desmoj.core.simulator.TimeSpan;
import desmoj.extensions.verkettung.abstractions.HasPredecessor;
import desmoj.extensions.verkettung.abstractions.HasSuccessor;
import desmoj.extensions.verkettung.abstractions.Station;
import desmoj.extensions.verkettung.util.MergerConfig;

/**
* The Merger merges the in the Mergerconfig defined entities into the EEx entity. The Merger waits until enough entities of the required types are in
* the internal partsQueue and than creates a PartsContainer. With this PartsContainer the StationStartevent is scheduled instantly and the common run
* through the internal Station stages can be conducted.
*
* @author Christian Mentz
*
@param <EIn>
*            the entitiy which comes in the Transformer
* @param <EEx>
*            the entity which leaves the Transformer
*/
public abstract class Merger<EIn extends Entity, EEx extends Entity> extends Station<EIn> implements
    HasPredecessor<EIn>, HasSuccessor<EEx> {

  /**
   * The MergerStartEvent takes an incomming entity and puts it into the queue for the entities type. If there is no queue for the entities type the
   * entity is discarded. If enough entites of the required ratio to create the outgoing entity are available, the Startevent of the Station is
   * scheduled.
   *
   * @author Christian Mentz
   *
   */
  class MergerStartEvent extends Event<EIn> {

    public MergerStartEvent(Model owner, String name, boolean showInTrace) {
      super(owner, name, showInTrace);
    }

    @Override
    public void eventRoutine(EIn who) {
      Queue<EIn> partsQueue;
      PartsContainer partsContainer;

      partsQueue = getPartsQueueForIncomingEntityClass(who.getClass());

      if (partsQueue == null) {
        sendWarning(
            "The Merger received a non specified entity and did not handle it",
            "MergerStartEvent : " + getName() + " Method: eventRoutine()",
            "The received entity is nit defnied in the MergerConfig",
            "Most likely you forgot to define the Mergerconfig properly or the Merger is not appropriate connected to the previous construct");

        throw new RuntimeException("Keine PartsQueue gefunden");
      }

      partsQueue.insert(who);

      partsContainer = tryToComposePartsContainerFromAvailableParts();
      if (partsContainer != null) {
        scheduleStationStartEventForPartsContainer(partsContainer);
      }
    }
  }

  /**
   * Utilitiy class which is created to run through the Station if enough entities are in the internal parts queues.
   *
   * @author Christian Mentz
   *
   */
  class PartsContainer extends Entity {
    /**
     * the parts from the different queues
     */
    private final Map<Class<? extends EIn>, List<EIn>> parts;

    /**
     * Constructor
     *
     * @param parts
     *            a map of the parts
     */
    public PartsContainer(Map<Class<? extends EIn>, List<EIn>> parts) {
      super(Merger.this.getModel(), "PartsContainer", true);
      this.parts = parts;
    }

    /**
     * Returns the parts of entities required to create the outgoing entity
     *
     * @return the parts
     */
    public Map<Class<? extends EIn>, List<EIn>> getParts() {
      return parts;
    }

  }

  /**
   * the succsessor event scheduled at the end of the Merger
   */
  private Event<? super EEx> successorEvent;
  /**
   * a map of queues which contains the incomming entities separeted by class of the entity
   */
  private final HashMap<Class<? extends EIn>, Queue<EIn>> incomingEntitiesQueueContainer;
  /**
   * the Mergerconfig which holds the required entities and ratios
   */
  private final MergerConfig<EIn> mergerConfig;

  /**
   * This Constructor sets the mergerconfig, the given times, initializes the queues and fills the free service capacity queue. If a given int is
   * lower than zero the station assumes that there is no resriction. This applies to incomingBufferQueueCapacity, maxEntitiesToHandle,
   * parallelHandledEntities. Furthermore the incoming entities queue container is initialized to hold the incomming entities.
   *
   * @param mergerConfig
   *            the Mergerconfig which holds the required entities and ratios
   * @param incomingBufferQueueCapacity
   *            the capatiy of the income queue
   * @param maxEntitiesToHandle
   *            the number of max entities the station can handle
   * @param parallelHandledEntities
   *            the number of max parallel entities a station can handle
   * @param setupTime
   *            the time the station needs to set up
   * @param serviceTime
   *            the time the station needs for the service
   * @param recoveryTime
   *            the time the station needs tor recover
   * @param transportTime
   *            the time the station needs to transport the entitiy to the next station
   * @param owner
   *            the model owner
   * @param name
   *            the name of the station
   * @param showInReport
   *            should this construct be in the report
   * @param showInTrace
   *            should this construct be in the trace
   */
  public Merger(MergerConfig<EIn> mergerConfig, int incomingBufferQueueCapacity, int maxEntitiesToHandle,
      int parallelHandledEntities, NumericalDist<?> setupTime, NumericalDist<?> serviceTime,
      NumericalDist<?> recoveryTime, NumericalDist<?> transportTime, Model owner, String name,
      boolean showInReport, boolean showInTrace) {

    super(incomingBufferQueueCapacity, maxEntitiesToHandle, parallelHandledEntities, setupTime,
        serviceTime, recoveryTime, transportTime, owner, name, showInReport, showInTrace);

    this.mergerConfig = mergerConfig;

    incomingEntitiesQueueContainer = new HashMap<Class<? extends EIn>, Queue<EIn>>();
    for (Class<? extends EIn> entityClass : mergerConfig.keySet()) {
      incomingEntitiesQueueContainer.put(entityClass, new Queue<EIn>(getModel(), getName() + "Incoming"
          + entityClass.getSimpleName() + "PufferQueue", showInReport, showInTrace));
    }
  }

  /**
   * Gets a reference to the previously by the constructor created queue for the given class incomingEntityClass If a queue for the entities class
   * cannot be found this method searches for superclasses of the entitiy. This gives the possibility to use a for instance a Tire class queue for
   * RedTires classes
   *
   * @param incomingEntityClass
   *            the entities class to search the appropriate queue
   *
   * @return returns the appropriate queue
   */
  private Queue<EIn> getPartsQueueForIncomingEntityClass(Class<? extends Entity> incomingEntityClass) {
    Queue<EIn> partsQueue;

    partsQueue = incomingEntitiesQueueContainer.get(incomingEntityClass);

    if (partsQueue == null) {
      for (Class<? extends EIn> possibleSuperClass : incomingEntitiesQueueContainer.keySet()) {
        if (possibleSuperClass.isAssignableFrom(incomingEntityClass)) {
          partsQueue = incomingEntitiesQueueContainer.get(possibleSuperClass);
          break;
        }
      }
    }

    return partsQueue;
  }

  /**
   * returns the Startevent of the Merger
   */
  @Override
  public Event<EIn> getStartEvent() {
    return new MergerStartEvent(getModel(), getName() + "_MergerStartEvent", true);
  }

  /**
   * This Method has to be overriden by the user and creates the outgoing entity. The user has the possibility to use the incomming entities of the
   * Merger to define the new entitiy
   *
   * @param parts
   *            a reference to the parts list
   * @return the outgoing entity which leaves the Merger
   */
  protected abstract EEx mergeEntities(Map<Class<? extends EIn>, List<EIn>> parts);

  /**
   * This method schedules the succsessor event with the defined transport time.
   */
  @Override
  @SuppressWarnings("unchecked")
  protected void onServiceFinisched(EIn who) {
    PartsContainer partsContainer = ((PartsContainer) who);

    try {
      successorEvent.clone().schedule(mergeEntities(partsContainer.getParts()), getTransportTime());
    } catch (CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * schedules the StationStartEvent with the internal created Partscontainer
   *
   * @param partsContainer
   */
  @SuppressWarnings("unchecked")
  private void scheduleStationStartEventForPartsContainer(PartsContainer partsContainer) {
    EIn entityToSchedule;

    entityToSchedule = ((EIn) partsContainer);

    super.getStartEvent().schedule(entityToSchedule, new TimeSpan(0));
  }

  @Override
  public void setSuccessor(Event<? super EEx> eventToScheduleWhenFinished) {
    successorEvent = eventToScheduleWhenFinished;
  }

  @Override
  public void setSuccessor(HasPredecessor<? super EEx> successor) {
    setSuccessor(successor.getStartEvent());
  };

  /**
   * This method trys to compose the Partscontainer with the entities in the parts queues.
   *
   * @return the PartsContainer if succsess or null if there a not enough entities in the parts queues
   */
  private PartsContainer tryToComposePartsContainerFromAvailableParts() {
    boolean enoughPartsAvailable;
    Map<Class<? extends EIn>, List<EIn>> allParts;

    enoughPartsAvailable = true;

    for (Class<? extends Entity> entityClass : mergerConfig.keySet()) {
      Integer requiredPartsCount = mergerConfig.get(entityClass);

      if (requiredPartsCount > getPartsQueueForIncomingEntityClass(entityClass).length()) {
        enoughPartsAvailable = false;
        break;
      }
    }

    if (enoughPartsAvailable) {
      allParts = new HashMap<Class<? extends EIn>, List<EIn>>();

      for (Class<? extends EIn> entityClass : mergerConfig.keySet()) {
        Integer requiredPartsCount;
        Queue<EIn> partsQueue;
        List<EIn> parts;

        requiredPartsCount = mergerConfig.get(entityClass);
        partsQueue = getPartsQueueForIncomingEntityClass(entityClass);
        parts = new ArrayList<EIn>();

        for (int i = 0; i < requiredPartsCount; i++) {
          EIn entity = partsQueue.first();
          partsQueue.remove(entity);
          parts.add(entity);
        }

        allParts.put(entityClass, parts);
      }
      return new PartsContainer(allParts);
    } else {
      return null;
    }
  }

}
TOP

Related Classes of desmoj.extensions.verkettung.Merger$MergerStartEvent

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.