Package jmt.gui.common.controller

Source Code of jmt.gui.common.controller.ModelChecker

/**   
  * Copyright (C) 2006, Laboratorio di Valutazione delle Prestazioni - Politecnico di Milano

  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.

  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.

  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */

package jmt.gui.common.controller;

import java.util.*;


import jmt.gui.common.CommonConstants;
import jmt.gui.common.definitions.BlockingRegionDefinition;
import jmt.gui.common.definitions.ClassDefinition;
import jmt.gui.common.definitions.SimulationDefinition;
import jmt.gui.common.definitions.StationDefinition;
import jmt.gui.common.definitions.parametric.ParametricAnalysisChecker;
import jmt.gui.common.definitions.parametric.ParametricAnalysisDefinition;
import jmt.gui.common.distributions.Distribution;
import jmt.gui.common.routingStrategies.LoadDependentRouting;
import jmt.gui.common.routingStrategies.ProbabilityRouting;
import jmt.gui.common.routingStrategies.RandomRouting;
import jmt.gui.common.routingStrategies.RoutingStrategy;
import jmt.gui.common.serviceStrategies.LDStrategy;

/**
* <p>Title: ModelChecker</p>
* <p>Description: Checks the model correctness</p>
*
* @author Francesco D'Aquino
*         Date: 6-ott-2005
*         Time: 16.12.50
*
* @author Bertoli Marco
*         (new errors)
*        
* Modified by Ashanka (May 2010):
* Patch: Multi-Sink Perf. Index
* Description: Added new Performance index for the capturing the
*         1. global response time (ResponseTime per Sink)
*              2. global throughput (Throughput per Sink)
*              each sink per class.
* Hence new validations are required to check the Performance Indices of
* response per sink and throughput per sink follow the model validations.
* 1. Response Time per Sink and Throughput per Sink should have a sink in
* the model.
* 2. Response Time per Sink and Throughput per Sink should not be selected
* with a closed class as for a closed model till now in JMT no jobs are
* routed to the sink and apparently sink is allowed to choose only when a
* open class is present.
*
* Modified by Ashanka (June 2010):
* Added Sink Probability for Closed class update to 0.0 warning message.
*/
public class ModelChecker implements CommonConstants {
  private ClassDefinition class_def;
  private StationDefinition station_def;
  private SimulationDefinition simulation_def;
  private BlockingRegionDefinition blocking_def;

  //sets the behavior of the checker
  private boolean isToJMVAChecker;

  //Variable that contains information about problems
  private boolean[] errors;
  //Variable that contains information about warnings
  private boolean[] warnings;
  //Vector containing the keys of the classes without a reference station
  private Vector<Object> classesWithoutRefStation;
  //Vector containing only the keys of the open classes without a reference station
  private Vector<Object> openClassesWithoutRefStation;
  //Vector containing the keys of the sources without a class associated to
  private Vector<Object> sourceWithoutClasses;
  //Vector containing the keys of stations with link problems
  private Vector<Object> stationsWithLinkErrors;
  // HashMap containing the vector of keys of the stations where
  // routing problems for this close class occour. The key of the
  // Hash Map is the key of the closed class considered
  private HashMap<Object, Vector<Object>> routingErrors;
  // HashMap containing the vector of keys of the stations reacheable by a close class
  //  The key of the Hash Map is the key of the closed class considered
  private HashMap<Object, Vector<Object>> allForwardStationsAreSinkErrors;
  //Vector containing the keys of measures defined more than once
  private Vector<Object> redundantMeasure;
  //Vector containing the inconsistent performance indexes
  private Vector<Object> inconsistentMeasures;
  //Vector containing the keys of servers with per class different
  //queue startegies
  private Vector<Object> BCMPserversWithDifferentQueueStrategy;
  //Vector containing the keys of servers with FCFS queueing strategy
  //but mixed types of service
  private Vector<Object> BCMPserversWithDifferentServiceTypes;
  //Vector containing the keys of servers with FCFS queue strategy
  // but a non exponential distribution
  private Vector<Object> BCMPserversFCFSWithoutExponential;
  //Vector containing the keys of servers with FCFS, the same
  //type of service for each class, but with different mean service
  //times
  private Vector<Object> BCMPFcfsServersWithDifferentServiceTimes;
  //Vector containing the keys of delays with at least a service time
  //distribution with a non rational Laplace transform
  private Vector<Object> BCMPdelaysWithNonRationalServiceDistribution;
  //Vector containing the keys of the stations where a non random routing is used.
  //Used only in JMVA conversion
  private Vector<Object> BCMPnonStateIndependentRoutingStations;
  //Vector containing the stations (not Sinks or Sources) not backward connected. Used for
  // warnings
  private Vector<Object> stationWithoutBackwardLinks;
  /** Empty blocking regions */
  private Vector<Object> emptyBlockingRegions;
  //Vector containing the keys of cs with wrong matrix(sum by rows less than 1)
  private Vector<Object> csWithWrongMatrix;
  //Vector containing the keys of cs followed by queue with drop bas stratregy
  private Vector<Object> csFollowedByBas;
  //Vector containing the keys of cs between fork/join
  private Vector<Object> csBetweenForkJoin;

    private Map<Object, HashMap<Object, Object>> invalidLoadDependentRouting;

  //Vector containing the keys of the stations with a queue strategy different from FCFS.
  //Used only in JMVA conversion
  //private Vector nonFCFSStations;

  //constant used to define an error
  public static int ERROR_PROBLEM = 0;
  //constant used to define a warning
  public static int WARNING_PROBLEM = 1;

  //it occours when no classes have been defined
  public static int NO_CLASSES_ERROR = 0;
  //it occours when no station have been defined
  public static int NO_STATION_ERROR = 1;
  //it occours when no measure have been defined
  public static int SIMULATION_ERROR = 2;
  //it occours when there is a sink but no open classes have been defined
  public static int SINK_BUT_NO_OPEN_CLASSES_ERROR = 3;
  //it occours when there is an open class but no sources have been defined
  public static int OPEN_CLASS_BUT_NO_SOURCE_ERROR = 4;
  //it occours when no open classes have been associated to a source
  public static int SOURCE_WITH_NO_OPEN_CLASSES_ERROR = 5;
  //it occours when a class hasn't a reference station
  public static int REFERENCE_STATION_ERROR = 6;
  //it occours when there is an open class but no sinks have been defined
  public static int NO_SINK_WITH_OPEN_CLASSES_ERROR = 7;
  //it occours when a station is not properly linked
  public static int STATION_LINK_ERROR = 8;
  //it occours when a close class is routed with probability 1 into a sink
  public static int ROUTING_ERROR = 9;
  //it occours when a close class is routed into a station whose forward stations are all sinks
  public static int ALL_FORWARD_STATION_ARE_SINK_ERROR = 10;
  //it occours if the same measure is defined more than once
  public static final int DUPLICATE_MEASURE_ERROR = 11;
  //it occours if one or performance index has one or more null field
  public static final int INCONSISTENT_MEASURE_ERROR = 12;
  //It occours only when trying to switch from JSim or JModel to JMVA, if there is at least
  //one open class without a reference station
  //public static final int OPEN_CLASS_REFERENCE_STATION_ERROR = 13;
  //it occours when there is at least one join but not a fork;
  public static final int JOIN_WITHOUT_FORK_ERROR = 13;
  //All jobs splitted by a fork must be routed to the same sink, or
  //to the same join
  public static final int FORK_JOIN_ROUTING_ERROR = 14;
  /** Empty blocking region */
  public static final int EMPTY_BLOCKING_REGION = 15;
  /** Preloaded station in a blocking region */
  public static final int PRELOADING_WITH_BLOCKING = 16;
 
  //Checks if XperSink and RperSink is selected with any sink in the model.
  public static final int SINK_PERF_IND_WITH_NO_SINK_ERROR = 17;
  //Checks if XperSink and RperSink is selected with closed classes.
  public static final int SINK_PERF_WITH_CLOSED_CLASS_ERROR = 18;
  //Checks if exist some rows of a Cs matrix that sum to a number less than one.
  public static final int CS_MATRIX_HAS_ROWS_LESS_THAN_ONE = 19;
  //Checks if exist some cs followed by a queue with bas drop strategy.
  public static final int CS_FOLLOWED_BY_A_BAS = 20;
  //Checks if exist some cs between a fork and a join.
  public static final int CS_BETWEEN_FORK_JOIN = 21;

    public static final int LOAD_DEPENDENT_ROUTING_INVALID = 22;

  //it occours when more than one sink have been defined
  public static int MORE_THAN_ONE_SINK_WARNING = 0;
  //it occours when a station (not sink or source) is not backward linked
  public static int NO_BACKWARD_LINK_WARNING = 1;
  //it occours if there is a fork but not a join
  public static int FORK_WITHOUT_JOIN_WARNING = 2;
  //It occours if the parametric analysis model has become inconsistent
  //with the model definition. This warning advices user to recheck the
  //parametric model definition, since it had been modified to make it
  //consistent back again.
  public static int PARAMETRIC_ANALYSIS_MODEL_MODIFIED_WARNING = 3;
  //It occours if a no PA are avaible, but a PA model was previously defined
  public static int PARAMETRIC_ANALYSIS_NO_MORE_AVAIBLE_WARNING = 4;
  //It occours if the station has diffrent per class queueing
  // strategy. (only when trying to convert to JMVA)
  public static int BCMP_DIFFERENT_QUEUEING_STRATEGIES_WARNING = 5;
  //It occours if the service policy inside a station with FCFS
  //queueing strategy, differs from class to class. In fact,
  //according to the BCMP theorem hypothesis, the service times
  //in an FCFS station must be all load independent or independent,
  //mixtures are not allowed
  public static int BCMP_FCFS_DIFFERENT_SERVICE_TYPES_WARNING = 6;
  //It occours if the station has a FCFS queueing strategy, but
  //the service time distribution is not exponential
  public static int BCMP_FCFS_EXPONENTIAL_WARNING = 7;
  //It occours if the station has a FCFS queueing strategy, but
  //the per class mean values of service time differ
  // (only when trying to convert to JMVA)
  public static int BCMP_FCFS_DIFFERENT_SERVICE_TIMES_WARNING = 8;
  //It occours if the station has a Processor Sharing service strategy
  //but it is not possible to define a Laplace rational transform
  //for the service time distribution
  // (only when trying to convert to JMVA)
  public static int BCMP_PROCESSOR_SHARING_WARNING = 9;
  //It occours if the station has a delay behavior but it is not
  //possible to define a Laplace rational transform for a
  //service time distribution
  // (only when trying to convert to JMVA)
  public static int BCMP_DELAY_WARNING = 10;
  //It occours if the station has a LCFS - Preemptive Resume
  //queueing strategy but it is not possible to define a
  //Laplace rational transform for the service time distribution
  // (only when trying to convert to JMVA)
  public static int BCMP_LCFS_PR_WARNING = 11;
  //It occours if the routing strategy is state dependent
  // (only when trying to convert to JMVA)
  public static int BCMP_NON_STATE_INDEPENDENT_ROUTING_WARNING = 12;

  public static int SINK_PROBABILITY_UPDATE_WARNING = 13;
 
  /*
  //It occours only when trying to switch from JSim or JModel to JMVA, if there is at least
  //one non exponential distribution
  public static int NO_EXP_FOUND_WARNING = 2;
  //it occours only when trying to convert to JMVA
  public static int DIFFERENT_SERVICE_TIME_WARNING = 3;
  //it occours only when trying to convert to JMVA
  public static int NON_FCFS_WARNING = 4;
  //it it occours only when trying to convert to JMVA
  public static int NON_STATE_INDEPENDENT_ROUTING_WARNING = 5;
  */


  private int NUMBER_OF_ERROR_TYPES = 23;
  private int NUMBER_OF_NORMAL_ERROR_TYPES = 23;
  private int NUMBER_OF_WARNING_TYPES = 14;
  private int NUMBER_OF_NORMAL_WARNING_TYPES = 5;

  /**
   * Creates a new modelchecker
   * @param class_def reference to class definition data structure
   * @param station_def reference to station definition data structure
   * @param simulation_def reference to simulation definition data structure
   * @param bd reference to blocking region definition data structure
   * @param isToJMVA true if model must be converted to jmva, false otherwise
   */
  public ModelChecker(ClassDefinition class_def, StationDefinition station_def, SimulationDefinition simulation_def, BlockingRegionDefinition bd,
      boolean isToJMVA) {
    this.class_def = class_def;
    this.station_def = station_def;
    this.simulation_def = simulation_def;
    this.blocking_def = bd;
    errors = new boolean[NUMBER_OF_ERROR_TYPES];
    warnings = new boolean[NUMBER_OF_WARNING_TYPES];
    classesWithoutRefStation = new Vector<Object>(0, 1);
    openClassesWithoutRefStation = new Vector<Object>(0, 1);
    sourceWithoutClasses = new Vector<Object>(0, 1);
    stationsWithLinkErrors = new Vector<Object>(0, 1);
    routingErrors = new HashMap<Object, Vector<Object>>(0, 1);
    allForwardStationsAreSinkErrors = new HashMap<Object, Vector<Object>>(0, 1);
    stationWithoutBackwardLinks = new Vector<Object>(0, 1);
    redundantMeasure = new Vector<Object>(0, 1);
    inconsistentMeasures = new Vector<Object>(0, 1);
    BCMPserversWithDifferentQueueStrategy = new Vector<Object>(0, 1);
    BCMPserversWithDifferentServiceTypes = new Vector<Object>(0, 1);
    BCMPserversFCFSWithoutExponential = new Vector<Object>(0, 1);
    BCMPFcfsServersWithDifferentServiceTimes = new Vector<Object>(0, 1);
    BCMPdelaysWithNonRationalServiceDistribution = new Vector<Object>(0, 1);
        invalidLoadDependentRouting = new HashMap<Object, HashMap<Object, Object>>(0);
    csWithWrongMatrix = new Vector<Object>(0, 1);
    csFollowedByBas = new Vector<Object>(0, 1);
    csBetweenForkJoin = new Vector<Object>(0, 1);
    //nonFCFSStations = new Vector(0,1);
    BCMPnonStateIndependentRoutingStations = new Vector<Object>(0, 1);
    emptyBlockingRegions = new Vector<Object>(0, 1);
    isToJMVAChecker = isToJMVA;
    checkModel();
  }

  //resets all the variables of the model checker
  private void reset() {
    openClassesWithoutRefStation.removeAllElements();
    classesWithoutRefStation.removeAllElements();
    sourceWithoutClasses.removeAllElements();
    stationsWithLinkErrors.removeAllElements();
    routingErrors.clear();
    allForwardStationsAreSinkErrors.clear();
    stationWithoutBackwardLinks.removeAllElements();
    redundantMeasure.removeAllElements();
    inconsistentMeasures.clear();
    //nonFCFSStations.removeAllElements();
    BCMPserversWithDifferentQueueStrategy.removeAllElements();
    BCMPserversWithDifferentServiceTypes.removeAllElements();
    BCMPserversFCFSWithoutExponential.removeAllElements();
    BCMPFcfsServersWithDifferentServiceTimes.removeAllElements();
    BCMPdelaysWithNonRationalServiceDistribution.removeAllElements();
    BCMPnonStateIndependentRoutingStations.removeAllElements();
    csWithWrongMatrix.removeAllElements();
    csFollowedByBas.removeAllElements();
    csBetweenForkJoin.removeAllElements();
    emptyBlockingRegions.removeAllElements();
        invalidLoadDependentRouting.clear();
    for (int i = 0; i < NUMBER_OF_ERROR_TYPES; i++) {
      errors[i] = false;
      if (i < NUMBER_OF_WARNING_TYPES) {
        warnings[i] = false;
      }
    }
  }

  //checks for problems of the model
  public void checkModel() {
    reset();

    if (isToJMVAChecker) {
      checkForNoClassError();
      checkForNoStationError();
      checkForOpenClassButNoSourceError();
      checkForRefStationError();
      //checkForOpenClassReferenceStationError();
      //checkForNoExpFoundWarning();
      //checkForDifferentServiceTimesWarnings();
      //checkForNonFCFSWarning();
      checkForBCMPDifferentQueueingStrategyWarning();
      checkForBCMPFcfsDifferentServiceTypesWarning();
      checkForBCMPFcfsNonExponentialWarning();
      checkForBCMPFcfsDifferentServiceTimesWarning();
      checkForBCMPProcessorSharingWarning();
      checkForBCMPDelayWarning();
      checkForBCMPLcfsPrWarning();
      checkForBCMPNonStateIndependentRoutingWarning();
    } else {
      station_def.manageProbabilities();
      checkForNoClassError();
      checkForNoStationError();
      checkForRefStationError();
      checkForOpenClassButNoSourceError();
      checkForSourcesWithNoClassesError();
      checkForNoSinkWithOpenClassError();
      checkForSinkButNoOpenClassError();
      checkForStationLinkError();
      checkForRoutingError();
      checkForAllForwardStationsAreSinkError();
      checkForSimulationError();
      checkForMeasureError();
      checkForInconsistentMeasureError();
            checkForLoadDependentRoutingError();
      //checkForMoreThanOneSinkWarning();
      checkForNoBacwardLinkWarning();
      checkForParametricAnalysisModelModifiedWarning();
      checkForParametricAnalysisNoMoreAvaibleWarning();
      checkForJoinWithoutForkErrors();
      checkForForkWithoutJoinWarnings();
      checkForEmptyBlockingRegions();
      checkForPreloadingInBlockingRegions();
      checkForSinkPerfIndicesWithNoSink();
      checkForSinkPerfIndicesWithClosedClass();
      checkForSinkProbabilityUpdateWarning();
      checkForCsMatrixProbabilities();
      checkForCsFollowedByBAS();
      checkForCsBetweenForkJoin();
    }

  }

  public StationDefinition getStationModel() {
    return station_def;
  }

  public ClassDefinition getClassModel() {
    return class_def;
  }

  public BlockingRegionDefinition getBlockingModel() {
    return blocking_def;
  }

  public boolean isToJMVA() {
    return isToJMVAChecker;
  }

  public boolean isEverythingOkNormal() {
    boolean ok = false;

    //for (int i=0; i<NUMBER_OF_NORMAL_ERROR_TYPES; i++) if (errors[i] == true) ok = false;
    //for (int i=0; i<NUMBER_OF_NORMAL_WARNING_TYPES; i++) if (warnings[i] == true) ok = false;
    if (isErrorFreeNormal() && isWarningFreeNormal()) {
      ok = true;
    }
    return ok;
  }

  public boolean isEverythingOkToJMVA() {
    boolean ok = false;

    if (isErrorFreeToJMVA() && isWarningFreeToJMVA()) {
      ok = true;
    }

    return ok;
  }

  public boolean isErrorFreeNormal() {
    for (int i = 0; i < NUMBER_OF_NORMAL_ERROR_TYPES; i++) {
      if (errors[i]) {
        return false;
      }
    }
    return true;
  }

  public boolean isErrorFreeToJMVA() {
    boolean ok = true;

    if ((errors[NO_CLASSES_ERROR]) || (errors[NO_STATION_ERROR]) || (errors[OPEN_CLASS_BUT_NO_SOURCE_ERROR]) || (errors[REFERENCE_STATION_ERROR])) {
      ok = false;
    }

    return ok;
  }

  public boolean isWarningFreeToJMVA() {
    boolean ok = true;
    if ((warnings[BCMP_DIFFERENT_QUEUEING_STRATEGIES_WARNING]) || (warnings[BCMP_FCFS_DIFFERENT_SERVICE_TYPES_WARNING])
        || (warnings[BCMP_FCFS_EXPONENTIAL_WARNING]) || (warnings[BCMP_FCFS_DIFFERENT_SERVICE_TIMES_WARNING])
        || (warnings[BCMP_PROCESSOR_SHARING_WARNING]) || (warnings[BCMP_DELAY_WARNING]) || (warnings[BCMP_LCFS_PR_WARNING])
        || (warnings[BCMP_NON_STATE_INDEPENDENT_ROUTING_WARNING])) {
      ok = false;
    }
    return ok;
  }

  public boolean isWarningFreeNormal() {
    boolean ok = true;
    for (int i = 0; i < NUMBER_OF_NORMAL_WARNING_TYPES; i++) {
      if (warnings[i]) {
        ok = false;
      }
    }
    if(warnings[SINK_PROBABILITY_UPDATE_WARNING]){//Added this seperatly other wise I had to redo the numbering,
      ok = false;
    }
    return ok;
  }

  /**
   * Returns true if no classes have been defined.
   * @return false, if there is at least one class
   * <br>true, if no classes have been defined
   */
  public boolean isThereNoClassesError() {
    return errors[NO_CLASSES_ERROR];
  }

  /**
   * Returns true if no stations have been defined.
   * @return false, if there is at least one station
   */
  public boolean isThereNoStationError() {
    return errors[NO_STATION_ERROR];
  }

  /**
   * Returns true if a reference station for each class have been defined.
   * @return false, if each class has a reference station
   */
  public boolean isThereClassesWithoutRefStationError() {
    return errors[REFERENCE_STATION_ERROR];
  }

  /**
   * Returns true if each source has an open class associated to.
   * @return false, if source has an open class associated to.
   */
  public boolean isThereSourceWithNoClassesError() {
    return errors[SOURCE_WITH_NO_OPEN_CLASSES_ERROR];
  }

  /**
   * Returns true if there is at least one open class but no sinks have been defined
   * @return true if the problem occours.
   */
  public boolean isThereNoSinkWithOpenClassesError() {
    return errors[NO_SINK_WITH_OPEN_CLASSES_ERROR];
  }

  /**
   * Returns true if there is at least a sink but no open classes have been defined
   * @return true if the problem occours
   */
  public boolean isThereSinkButNoOpenClassError() {
    return errors[SINK_BUT_NO_OPEN_CLASSES_ERROR];
  }

  /**
   * Returns true if there is at least one open class but no source has been defined
   * @return true if the problem occours
   */
  public boolean isThereOpenClassButNoSourceError() {
    return errors[OPEN_CLASS_BUT_NO_SOURCE_ERROR];
  }

  /**
   * Returns true if there is at least one station link error
   * @return true if the problem occours.
   */
  public boolean isThereStationLinkError() {
    return errors[STATION_LINK_ERROR];
  }

  /**
   * Returns true if there is at least one closed class routed into a station whose
   * forward stations are all sink
   * @return true if at least one routing problem was found
   */
  public boolean isThereAllForwardStationsAreSinkErrors() {
    return errors[ALL_FORWARD_STATION_ARE_SINK_ERROR];
  }

  /**
   * Returns true if there is at least one routing error (a closed class routed into a sink)
   * @return true if at least one routing problem was found
   */
  public boolean isThereRoutingError() {
    return errors[ROUTING_ERROR];
  }

  /**
   * Returns true if no measures have been defined
   * @return true if the problem occours
   */
  public boolean isThereSimulationError() {
    return errors[SIMULATION_ERROR];
  }

  /**
   * Returns true if the same measure is defined more than one time
   * @return true if the same measure is defined more than one time
   */
  public boolean isThereMeasureError() {
    return errors[DUPLICATE_MEASURE_ERROR];
  }

  /**
   * Returns true if there is at least one measure with at least one
   * 'null' field
   * @return true if the same measure is defined more than one time
   */
  public boolean isThereInconsistentMeasureError() {
    return errors[INCONSISTENT_MEASURE_ERROR];
  }

  public boolean isTherejoinWithoutForkError() {
    return errors[JOIN_WITHOUT_FORK_ERROR];
  }

  /**
   * Returns if a blocking region without stations error occurred
   * @return if a blocking region without stations error occurred
   * <br>Author: Bertoli Marco
   */
  public boolean isThereEmptyBlockingRegionError() {
    return errors[EMPTY_BLOCKING_REGION];
  }

  /**
   * Returns if a station in a blocking region is preloaded
   * @return if a station in a blocking region is preloaded
   * <br>Author: Bertoli Marco
   */
  public boolean isTherePreloadingInBlockingRegionError() {
    return errors[PRELOADING_WITH_BLOCKING];
  }
 
  public boolean isThereSinkPerfIndicesWithNoSinkError(){
    return errors[SINK_PERF_IND_WITH_NO_SINK_ERROR];
  }
 
  public boolean isSinkPerfIndicesWithClosedClassError(){
    return errors[SINK_PERF_WITH_CLOSED_CLASS_ERROR];
  }
 
  /**
   * Returns true if exist some class_switch
   * components with a invalid matrix (e.g. some
   * rows do not sum to a value grater or equals
   * to one.), returns false otherwise.
   * @return
   */
  public boolean isThereCsMatrixRowSumError() {
    return errors[CS_MATRIX_HAS_ROWS_LESS_THAN_ONE];
  }
 
  /**
   * Returns true if exist some class_switch
   * components followed by a queue implementing
   * the BAS stratregy, returns false otherwise.
   * @return
   */
  public boolean isThereCsFollowedByBasError() {
    return errors[CS_FOLLOWED_BY_A_BAS];
  }

    public boolean isThereLoadDependentRoutingError() {
    return errors[LOAD_DEPENDENT_ROUTING_INVALID];
  }

  /**
   * Returns true if exist some class_switch
   * components between a fork and a join, returns
   * false otherwise.
   * @return
   */
  public boolean isThereCsBetweenForkJoin() {
    return errors[CS_BETWEEN_FORK_JOIN];
  }


  /**
   * Checks the presence in the model of a non exponential time distribution. This is an
   * error only if user is trying to convert the model to JMVA
   * @return true if at least one non-exponential time distribution is found
   */
  /*public boolean isThereNoExpFoundWarning() {
      return warnings[NO_EXP_FOUND_WARNING];
  }

  /**
   * To be used only for the JSim/JModel to JMVA conversion
   * @return true if there is at least one open class without a reference station
   */
  /*public boolean isThereOpenClassReferenceStationError() {
      return errors[OPEN_CLASS_REFERENCE_STATION_ERROR];
  }*/

  /**
   * use it to check if there is at least one non FCFS queue policy in the model
   * @return true if at least one non FCFS queue policy is found in the model
   */
  /*public boolean isThereNonFCFSWarning() {
      return warnings[NON_FCFS_WARNING];
  }

  /**
   * Checks if there are delays in the model
   * @return true if at least a delay is found
   */
  /*public boolean isThereDelaysFoundError() {
      return errors[DELAYS_FOUND_ERROR];
  }*/

  /**
   * Returns true if more than one Sink have been defined. In order to maintain
   * the accuracy of the measured throughput.
   * @return true if more than one Sink have been defined
   */
  public boolean isThereMoreThanOneSinkWarning() {
    return warnings[MORE_THAN_ONE_SINK_WARNING];
  }

  /**
   * Checks if there is a station (not a sink or a source) no backward linked
   * @return true if there is at least a station (not a sink or a source) no backward linked
   */
  public boolean isThereNoBackwardLinkWarning() {
    return warnings[NO_BACKWARD_LINK_WARNING];
  }

  /**
   * Returns true if the PARAMETRIC_ANALYSIS_MODEL_MODIFIED_WARNING occours
   * @return true if the parametric analysis model had become inconsistent
   *         consequently it was modified
   */
  public boolean isThereParametricAnalysisModelModifiedWarning() {
    return warnings[PARAMETRIC_ANALYSIS_MODEL_MODIFIED_WARNING];
  }

  /**
   * Returns true if PARAMETRIC_ANALYSIS_NO_MORE_AVAIBLE_WARNING occours
   * @return true if no PA are avaible but a PA model was previously defined
   */
  public boolean isThereParametricAnalysisNoMoreAvaibleWarning() {
    return warnings[PARAMETRIC_ANALYSIS_NO_MORE_AVAIBLE_WARNING];
  }

  /**
   * Checks if the service times for different classes are different inside the same station
   * @return true if the problem occours
   */
  /*public boolean isThereDifferentServiceTimeWarning() {
      return warnings[DIFFERENT_SERVICE_TIME_WARNING];
  }
  */

  /**
   * Checks if there are servers with per class different queueing
   * strategy
   * @return true if servers with per class different queueing strategy
   *         are found
   */
  public boolean isThereBCMPDifferentQueueingStrategyWarning() {
    return warnings[BCMP_DIFFERENT_QUEUEING_STRATEGIES_WARNING];
  }

  /**
  * Checks if there are FCFS servers with a mixed service type
  * @return true if FCFS servers with with a mixed service type
  *         are found
  */
  public boolean isThereBCMPDifferentServiceTypeWarning() {
    return warnings[BCMP_FCFS_DIFFERENT_SERVICE_TYPES_WARNING];
  }

  /**
  * Checks if there are FCFS servers with omogeneous but non
  * exponential service type
  *
  * @return true if FCFS servers with omogeneous but non
  *         exponential service type are found
  */
  public boolean isThereBCMPFcfsNonExponentialWarning() {
    return warnings[BCMP_FCFS_EXPONENTIAL_WARNING];
  }

  /**
  * Checks if there are FCFS servers with omogeneous exponential
  * service type, but with different per class service times mean
  * values. If the service type is Load Dependent it checks that
  * for each class the load dependent strategies are the same, i.e. :
  * <br>1) have the same number of ranges</br>
  * <br>2) have the same distribution in each range (Exponential)</br>
  * <br>3) have the same mean value in each range</br>
  * <br>4) have the same 'from' and 'to' values in each range</br>
  *
  * @return true if FCFS servers with omogeneous exponential
  *         service type with different per class service times mean
  *         values are found
  */
  public boolean isThereBCMPFcfsDifferentServiceTimesWarning() {
    return warnings[BCMP_FCFS_DIFFERENT_SERVICE_TIMES_WARNING];
  }

  /**
  * Checks if there are delays with a service time distribution whose
  * Laplace transform is not rational
  *
  * @return true if delays with a service time distribution whith
  *         a non rational Laplace transform are found
  */
  public boolean isThereBCMPDelayWarning() {
    return warnings[BCMP_DELAY_WARNING];
  }

  /**
  * Checks if there are LCFS-PR stations with service time
  * distribution whose Laplace transform is not rational
  *
  * @return true if LCFS-PR stations with service time
  *         distribution whose Laplace transform is not rational
  */
  public boolean isThereBCMPLcfsPrWarning() {
    return warnings[BCMP_LCFS_PR_WARNING];
  }

  public boolean isThereForkWithoutJoinWarnings() {
    return warnings[FORK_WITHOUT_JOIN_WARNING];
  }

  /**
  * Checks if there are stations with Processor Sharing service
  * strategy with a service time distribution whose Laplace transform
  *  is not rational
  *
  * @return true if stations with Processor Sharing service
  *         strategy with a service time distribution whose Laplace
  *         transform is not rational are found
  */
  public boolean isThereBCMPProcessorSharingWarning() {
    return warnings[BCMP_PROCESSOR_SHARING_WARNING];
  }

  /**
   * Use it to check if a non random routing is used
   * @return true if a non random routing is used
   */
  public boolean isThereBCMPNonStateIndependentRoutingWarning() {
    return warnings[BCMP_NON_STATE_INDEPENDENT_ROUTING_WARNING];
  }

  /**
   * Returns a Vector<Object> containing the keys of the classes without a reference station. If every
   * has a reference station returns null.
   * @return a Vector<Object> containing the keys of the classes without a reference station.
   */
  public Vector<Object> getKeysOfClassesWithoutRefStation() {
    if (errors[REFERENCE_STATION_ERROR]) {
      return classesWithoutRefStation;
    } else {
      return null;
    }
  }

  /**
  * Returns a Vector<Object> containing the keys of OPEN classes without a reference station. If each
  * open class has a reference station returns null.
  * @return a Vector<Object> containing the keys of the classes without a reference station.
  */
  /*public Vector<Object> getKeysOfOpenClassesWithoutRefStation() {
      if (errors[OPEN_CLASS_REFERENCE_STATION_ERROR]) return openClassesWithoutRefStation;
      else return null;
  }*/

  /**
   * Returns a Vector<Object> containing the keys of the sources witch have no classes associated to. If every
   * source has a reference station or no source are defined returns null.
   * @return a Vector<Object> containing the keys of the sources with no classes associated to.
   */
  public Vector<Object> getKeysOfSourceWithoutClasses() {
    if (errors[SOURCE_WITH_NO_OPEN_CLASSES_ERROR]) {
      return sourceWithoutClasses;
    } else {
      return null;
    }
  }

  /**
  * Returns a Vector<Object> containing the keys of the stations whith link problems, such as:
  * <br>- a Source not forward linked.
  * <br>- a Server not forward linked.
  * <br>- a Delay not forward linked.
  * <br>- a Sink not backward linked.
  * <br><br>If there isn't any problem it returns null.
  * @return a Vector<Object> containing the keys of the stations with link problems.
  */
  public Vector<Object> getKeysOfStationsWithLinkProblems() {
    if (errors[STATION_LINK_ERROR]) {
      return stationsWithLinkErrors;
    } else {
      return null;
    }
  }

  /**
   * Returns a vector with all empty blocking regions
   * @return a vector with all empty blocking regions keys.
   */
  public Vector<Object> getKeysOfEmptyBlockingRegions() {
    if (errors[EMPTY_BLOCKING_REGION]) {
      return emptyBlockingRegions;
    } else {
      return null;
    }
  }

  /**
   * Returns a HashMap where the key is the key of a close class. For each close class that may
   * be routed into a station whose forward stations are all sink it contains a Vector<Object> with the
   * keys of the stations where the problems occours. If there isn't any problem or no close
   * classes are defined it returns null.
   *  @return a HashMap where the key is the key of a close class.
   */
  public HashMap<Object, Vector<Object>> getKeysOfAllForwardStationsAreSinkErrors() {
    if (errors[ALL_FORWARD_STATION_ARE_SINK_ERROR]) {
      return allForwardStationsAreSinkErrors;
    } else {
      return null;
    }
  }

  /**
   * Returns a HashMap where the key is the key of a close class. For each close class with a routing
   * problem it contains a Vector<Object> with the keys of the stations where the routing problems occours. If there isn't any problem
   * or no close classes are defined it returns null.
   *  @return a HashMap where the key is the key of a close class.
   */
  public HashMap<Object, Vector<Object>> getKeysOfRoutingProblems() {
    if (errors[ROUTING_ERROR]) {
      return routingErrors;
    } else {
      return null;
    }
  }

  /**
   * Get the Vector<Object> with station (no Sinks or Sources) not backward connected. Used
   * for warnings.
   * @return the Vector<Object> with station (no Sinks or Sources) not backward connected.
   */
  public Vector<Object> getKeysOfStationWithoutBackwardLinks() {
    if (warnings[NO_BACKWARD_LINK_WARNING]) {
      return stationWithoutBackwardLinks;
    } else {
      return null;
    }
  }

  /**
   * Use it to get a Vector<Object> containing the keys of servers with per
   * class different queue startegies
   * @return a Vector<Object> containing the keys of servers with per class
   *         different queue startegies
   */
  public Vector<Object> getBCMPserversWithDifferentQueueStrategy() {
    return BCMPserversWithDifferentQueueStrategy;
  }

  /**
   * Use it to get a Vector<Object> containing the keys of servers with FCFS
   * queueing strategy but mixed types of service
   * @return a Vector<Object> containing the keys of servers with FCFS
   *         queueing strategy but mixed types of service
   */
  public Vector<Object> getBCMPserversWithDifferentServiceTypes() {
    return BCMPserversWithDifferentServiceTypes;
  }
 
  /**
   * Use it to get a Vector<Object> containing the keys of css with a matrix
   * in which some rows sum to a value less than one
   * @return a Vector<Object> containing the keys of css with a matrix
   * in which some rows sum to a value less than one
   */
  public Vector<Object> getCsWithWrongMatrix() {
    return csWithWrongMatrix;
  }

  /**
   * Use it to get a Vector<Object> containing the keys of css followed
   * by a queue implementing a drop bas stratregy.
   * @return a Vector<Object> containing the keys of css followed
   * by a queue implementing a drop bas stratregy.
   */
  public Vector<Object> getCsFolloweByBas() {
    return csFollowedByBas;
 

  /**
   * Use it to get a Vector<Object> containing the keys of css between
   * fork/join.
   * @return a Vector<Object> containing the keys of css between
   * fork/join.
   */
  public Vector<Object> getCsBetweenForkJoin() {
    return csBetweenForkJoin;
 
 
  /**
   * Use it to get a Vector<Object> containing the keys of servers with FCFS
   * queueing strategy but a non exponential distribution
   * @return a Vector<Object> containing the keys of servers with FCFS
   *         queueing strategy but a non exponential distribution
   */
  public Vector<Object> getBCMPserversFCFSWithoutExponential() {
    return BCMPserversFCFSWithoutExponential;
  }

  /**
   * Use it to get a Vector<Object> containing the keys of servers with FCFS
   * queueing strategy, exponential distribution but different per
   * class service times
   * @return a Vector<Object> containing the keys of servers with FCFS
   *         queueing strategy, exponential distribution but different per
   *         class service times
   */
  public Vector<Object> getBCMPFcfsServersWithDifferentServiceTimes() {
    return BCMPFcfsServersWithDifferentServiceTimes;
  }

  /**
   * Use it to get a Vector<Object> containing the keys of delays with
   * at least a service time distribution with a non rational Laplace
   * transform
   * @return a Vector<Object> containing the keys of delays with
   *         at least a service time distribution with a non rational Laplace
   *         transform
   */
  public Vector<Object> getBCMPdelaysWithNonRationalServiceDistribution() {
    return BCMPdelaysWithNonRationalServiceDistribution;
  }

    public Map<Object, HashMap<Object, Object>> getInvalidLoadDependentRoutingStations() {
    return invalidLoadDependentRouting;
  }

  /**
   * Check that there is at least one class in the model. If a problem is found it raises
   * to "true" the corresponding position inside the problems array.
   */
  private void checkForNoClassError() {
    // get the vector of the keys of the classes
    Vector<Object> classKeys = class_def.getClassKeys();
    //if the vector is empty there are no classes defined in the model
    if (classKeys.size() == 0) {
      errors[NO_CLASSES_ERROR] = true;
    }
  }

  /**
   * Check that there is at least one station in the model. If a problem is found it raises
   * to "true" the corresponding position inside the problems array.
   */
  private void checkForNoStationError() {
    boolean noStation = true;
    // get the vector of the keys of the elements (stations, sinks, delays, servers)
    Vector<Object> elements = station_def.getStationKeys();
    //check each element...
    for (int i = 0; i < elements.size(); i++) {
      Object thisElement = elements.get(i);
      String type = station_def.getStationType(thisElement);
      if ((!type.equals(STATION_TYPE_SOURCE)) && (!type.equals(STATION_TYPE_SINK))) {
        noStation = false;
      }
    }
    if (noStation) {
      errors[NO_STATION_ERROR] = true;
    }
  }

  /**
   * Checks that every class has a reference station. If a problem is found it raises
   * to "true" the corresponding position inside the problems array.
   */
  private void checkForRefStationError() {
    // get the vector of the keys of the classes
    Vector<Object> classKeys = class_def.getClassKeys();

    for (int i = 0; i < classKeys.size(); i++) {
      //get the key at i
      Object thisKey = classKeys.get(i);
      //get the Reference Station of the class
      Object thisRefStation = class_def.getClassRefStation(thisKey);
      //if the class has no reference station there is a class problem
      if (thisRefStation == null) {
        errors[REFERENCE_STATION_ERROR] = true;
        classesWithoutRefStation.add(thisKey);
      }
    }
  }

  /**
   * Checks that there are no sources without a class associated to. If a problem is found it raises
   * to "true" the corresponding position inside the problems array.
   */
  private void checkForSourcesWithNoClassesError() {
    // get the vector of the keys of the stations
    Vector<Object> stationKeys = station_def.getStationKeys();

    for (int i = 0; i < stationKeys.size(); i++) {
      //get the sourceKey at i
      Object thisStationKey = stationKeys.get(i);
      //get the type of the station
      String type = station_def.getStationType(thisStationKey);
      if (type.equals(STATION_TYPE_SOURCE)) {
        //this variable is true if no classes are associated to this source
        boolean noClassesAssociated = true;
        //get the vector of the class keys....
        Vector<Object> classKeys = class_def.getClassKeys();
        for (int j = 0; j < classKeys.size(); j++) {
          //get the key of the class at j
          Object thisClassKey = classKeys.get(j);
          //get the key of the reference station of this class
          Object refStationKeyForThisClass = class_def.getClassRefStation(thisClassKey);
          //if the key of the reference station and the key of the source considered
          //are the same it means that there is at least one class associated to the source
          if (refStationKeyForThisClass == thisStationKey) {
            noClassesAssociated = false;
          }
        }
        //if the variable noClassesAssociated is still true it means that this source has
        //no classes associated to
        if (noClassesAssociated) {
          errors[SOURCE_WITH_NO_OPEN_CLASSES_ERROR] = true;
          sourceWithoutClasses.add(thisStationKey);
        }
      }
    }
  }

  /**
   * Check if there is at least one open class but there are no sinks. If a problem is found it raises
   * to "true" the corresponding position inside the problems array.
   */
  private void checkForNoSinkWithOpenClassError() {
    //vector used to contain the set of open class keys
    Vector<Object> openClasses = new Vector<Object>(0, 1);
    //vector used to contain the complete set class keys
    Vector<Object> classes = class_def.getClassKeys();
    //for cicle used to collect the open class keys from the classes vector
    for (int i = 0; i < classes.size(); i++) {
      Object thisClassKey = classes.get(i);
      if (class_def.getClassType(thisClassKey) == CLASS_TYPE_OPEN) {
        openClasses.add(thisClassKey);
      }
    }
    //if there is at least one open class
    if (openClasses.size() > 0) {
      //variable counting the number of sink
      int nSink = 0;
      //vector containing the complete set of class keys
      Vector<Object> stations = station_def.getStationKeys();
      //for each station ...
      for (int i = 0; i < stations.size(); i++) {
        Object thisStationKey = stations.get(i);
        // ... check if it is a sink, in that case increase the nSink variable
        if (station_def.getStationType(thisStationKey).equals(STATION_TYPE_SINK)) {
          nSink++;
        }
      }
      //if no sink was found there is an error
      errors[NO_SINK_WITH_OPEN_CLASSES_ERROR] = nSink == 0;
    } else {
      errors[NO_SINK_WITH_OPEN_CLASSES_ERROR] = false;
    }
  }

  /**
   * Checks if there is at least an open class but no source have been defined
   */
  private void checkForOpenClassButNoSourceError() {
    //variable used to count the number of open classes
    int openClasses = 0;
    //vector used to contain the complete set class keys
    Vector<Object> classes = class_def.getClassKeys();
    //for cicle used to collect the open class keys from the classes vector
    for (int i = 0; i < classes.size(); i++) {
      Object thisClassKey = classes.get(i);
      if (class_def.getClassType(thisClassKey) == CLASS_TYPE_OPEN) {
        openClasses++;
      }
    }
    if (openClasses == 0) {
      errors[OPEN_CLASS_BUT_NO_SOURCE_ERROR] = false;
    } else {
      //Vector<Object> containing the entire station key set
      Vector<Object> stations = station_def.getStationKeys();
      //variable counting the number of source
      int nSource = 0;
      for (int i = 0; i < stations.size(); i++) {
        Object thisStation = stations.get(i);
        String type = station_def.getStationType(thisStation);
        if (type.equals(STATION_TYPE_SOURCE)) {
          nSource++;
        }
      }
      //if no sources have been defined there is an error
      errors[OPEN_CLASS_BUT_NO_SOURCE_ERROR] = nSource == 0;
    }
  }

  /**
   * Checks if there is at least a sink but no open classes have been defined
   */
  private void checkForSinkButNoOpenClassError() {
    //vector used to contain the complete set of station keys
    Vector<Object> stationSet = station_def.getStationKeys();
    //variable used to count the number of sink station
    int nSink = 0;
    //for cycle used to count the number of sink
    for (int i = 0; i < stationSet.size(); i++) {
      Object thisStation = stationSet.get(i);
      String stationType = station_def.getStationType(thisStation);
      if (stationType.equals(STATION_TYPE_SINK)) {
        nSink++;
      }
    }
    if (nSink > 0) {
      //variable used to count the number of open class keys
      int nOpenClasses = 0;
      //vector used to contain the complete set class keys
      Vector<Object> classes = class_def.getClassKeys();
      //for cicle used to count the number of open class keys
      for (int i = 0; i < classes.size(); i++) {
        Object thisClassKey = classes.get(i);
        if (class_def.getClassType(thisClassKey) == CLASS_TYPE_OPEN) {
          nOpenClasses++;
        }
      }
      //if there is at least one open class
      errors[SINK_BUT_NO_OPEN_CLASSES_ERROR] = nOpenClasses <= 0;
    } else {
      errors[SINK_BUT_NO_OPEN_CLASSES_ERROR] = false;
    }
  }

  /**
   * Checks:
   * 1) Each Source is forward linked to something.
   * 2) Each Server is forward linked to something.
   * 3) Each Delay is forward linked to something.
   * 4) Each Sink is backward linked to something.
   * If a problem is found it raises to "true" the corresponding position
   * inside the problems array.
   */
  private void checkForStationLinkError() {
    // get the vector of the keys of the stations
    Vector<Object> stationKeys = station_def.getStationKeys();

    for (int i = 0; i < stationKeys.size(); i++) {
      //get the key of the station at i
      Object thisStationKey = stationKeys.get(i);
      //get the type of the station
      String stationType = station_def.getStationType(thisStationKey);

      if (stationType.equals(STATION_TYPE_SOURCE)) {
        //get the vector of forward links
        Vector<Object> connections = station_def.getForwardConnections(thisStationKey);
        //if the vector is empty the source is not forward connected
        if (connections.isEmpty()) {
          errors[STATION_LINK_ERROR] = true;
          stationsWithLinkErrors.add(thisStationKey);
        }

      }

      else if (stationType.equals(STATION_TYPE_SINK)) {
        //get the vector of backward links
        Vector<Object> connections = station_def.getBackwardConnections(thisStationKey);
        //if the vector is empty the Sink is not backward connected
        if (connections.isEmpty()) {
          errors[STATION_LINK_ERROR] = true;
          stationsWithLinkErrors.add(thisStationKey);
        }
      }

      else {
        //get the vector of forward links
        Vector<Object> connections = station_def.getForwardConnections(thisStationKey);
        //if the vector is empty the Server is not forward connected
        if (connections.isEmpty()) {
          errors[STATION_LINK_ERROR] = true;
          stationsWithLinkErrors.add(thisStationKey);
        }
      }

    }
  }

  /**
   * Checks for the existance of empty blocking regions
   * <br>Author: Bertoli Marco
   */
  private void checkForEmptyBlockingRegions() {
    Iterator<Object> regionKeys = blocking_def.getRegionKeys().iterator();
    while (regionKeys.hasNext()) {
      Object key = regionKeys.next();
      if (blocking_def.getBlockingRegionStations(key).size() == 0) {
        // Blocking region 'key' is empty
        emptyBlockingRegions.add(key);
        errors[EMPTY_BLOCKING_REGION] = true;
      }
    }
  }

  /**
   * Checks if a station in a blocking region is preloaded
   * <br>Author: Bertoli Marco
   */
  private void checkForPreloadingInBlockingRegions() {
    Iterator<Object> regionKeys = blocking_def.getRegionKeys().iterator();
    Vector<Object> classes = class_def.getClassKeys();
    while (regionKeys.hasNext()) {
      Object key = regionKeys.next();
      Set<Object> stations = blocking_def.getBlockingRegionStations(key);
      Iterator<Object> st = stations.iterator();
      while (st.hasNext()) {
        Object stationKey = st.next();
        for (int i = 0; i < classes.size(); i++) {
          if (simulation_def.getPreloadedJobs(stationKey, classes.get(i)).intValue() > 0) {
            errors[PRELOADING_WITH_BLOCKING] = true;
          }
        }
      }

      if (blocking_def.getBlockingRegionStations(key).size() == 0) {
        // Blocking region 'key' is empty
        emptyBlockingRegions.add(key);
        errors[EMPTY_BLOCKING_REGION] = true;
      }
    }
  }

  /**
   * Checks that no closed classes may be routed into a Sink. If a problem is found it raises
   * to "true" the corresponding position inside the errors array.
   */
  private void checkForRoutingError() {
    //vector collecting all the station keys where routing problems occour
    // for this close class
    Vector<Object> problemsPerClass = new Vector<Object>(0, 1);
    Vector<Object> closedClassKeys = class_def.getClosedClassKeys();
    Vector<Object> startingPoints = new Vector<Object>(0, 1);
    //get the vector of the possible starting points
    Vector<Object> noSourceSink = station_def.getStationKeysNoSourceSink();
    for (int i = 0; i < closedClassKeys.size(); i++) {
      //remove all elements from the problemsPerClass vector
      problemsPerClass.removeAllElements();
      //create the vector containing the already visited station keys
      Vector<Object> alreadyVisited = new Vector<Object>(0, 1);
      //get the class at i
      Object thisClassKey = closedClassKeys.get(i);
      //checks for each possible starting point if there are preloaded jobs for the class i.
      //In that case put it into the startingPoints vector
      for (int j = 0; j < noSourceSink.size(); j++) {
        Object thisElementKey = noSourceSink.get(j);
        int preloadedJobs = simulation_def.getPreloadedJobs(thisElementKey, thisClassKey).intValue();
        if (preloadedJobs > 0) {
          startingPoints.add(thisElementKey);
        }
      }
      //start the explore algorithm for each of the station containing some preloaded jobs for class i
      for (int j = 0; j < startingPoints.size(); j++) {
        //get the element at j
        Object thisStartingPoint = startingPoints.get(j);
        //if this possible starting point has not been visited yet
        if (!alreadyVisited.contains(thisStartingPoint)) {
          alreadyVisited.add(thisStartingPoint);
          Vector<Object> problemsForThisStartingPoint = exploreForRoutingProblems(thisClassKey, thisStartingPoint, alreadyVisited);
          for (int k = 0; k < problemsForThisStartingPoint.size(); k++) {
            problemsPerClass.add(problemsForThisStartingPoint.get(k));
          }
        }
      }
      if (!problemsPerClass.isEmpty()) {
        routingErrors.put(thisClassKey, (Vector<Object>) problemsPerClass.clone());
        errors[ROUTING_ERROR] = true;
      }
    }
  }

  /**
   * Checks that no closed classes may be routed into a station whose forward station(s) are
   * all sink. If a problem is found it raises to "true" the corresponding position inside
   * the errors array.
   */
  private void checkForAllForwardStationsAreSinkError() {
    //vector collecting all the station keys where errors occour
    // for this close class
    Vector<Object> problemsPerClass = new Vector<Object>(0, 1);
    Vector<Object> closedClassKeys = class_def.getClosedClassKeys();
    Vector<Object> startingPoints = new Vector<Object>(0, 1);
    //get the vector of the possible starting points
    Vector<Object> noSourceSink = station_def.getStationKeysNoSourceSink();
    for (int i = 0; i < closedClassKeys.size(); i++) {
      //remove all elements from the problemsPerClass vector
      problemsPerClass.removeAllElements();
      //create the vector containing the already visited station keys
      Vector<Object> alreadyVisited = new Vector<Object>(0, 1);
      //get the class at i
      Object thisClassKey = closedClassKeys.get(i);
      //checks for each possible starting point if there are preloaded jobs for the class i.
      //In that case put it into the startingPoints vector
      for (int j = 0; j < noSourceSink.size(); j++) {
        Object thisElementKey = noSourceSink.get(j);
        int preloadedJobs = simulation_def.getPreloadedJobs(thisElementKey, thisClassKey).intValue();
        if (preloadedJobs > 0) {
          startingPoints.add(thisElementKey);
        }
      }
      //start the explore algorithm for each of the station containing some preloaded jobs for class i
      for (int j = 0; j < startingPoints.size(); j++) {
        //get the element at j
        Object thisStartingPoint = startingPoints.get(j);
        //if this possible starting point has not been visited yet
        if (!alreadyVisited.contains(thisStartingPoint)) {
          alreadyVisited.add(thisStartingPoint);
          Vector<Object> problemsForThisStartingPoint = this.exploreForAllForwardStationAreSink(thisClassKey, thisStartingPoint,
              alreadyVisited);
          for (int k = 0; k < problemsForThisStartingPoint.size(); k++) {
            problemsPerClass.add(problemsForThisStartingPoint.get(k));
          }
        }
      }
      if (!problemsPerClass.isEmpty()) {
        allForwardStationsAreSinkErrors.put(thisClassKey, (Vector<Object>) problemsPerClass.clone());
        errors[ALL_FORWARD_STATION_ARE_SINK_ERROR] = true;
      }
    }
  }

  /**
   * Checks for NO_EXP_FOUND_ERROR
   */
  /*private void checkForNoExpFoundWarning() {
      Vector<Object> classes = class_def.getClassKeys();
      //first search for open classes with non exponential arrival time distribution
      for (int i=0; i<classes.size();i++) {
          Object thisKey = classes.get(i);
          if (class_def.getClassType(thisKey) == CLASS_TYPE_OPEN) {
              Object distribution = class_def.getClassDistribution(thisKey);
              if ((distribution != null)&&(!(distribution instanceof Exponential))) {
                  warnings[NO_EXP_FOUND_WARNING] = true;
                  return;
              }
          }
      }
      //than search for non exponential service time distribution
      Vector<Object> stations = station_def.getStationKeys();
      for (int i=0; i<stations.size();i++) {
          Object thisStation = stations.get(i);
          for (int j=0; j<classes.size();j++) {
              Object thisClass = classes.get(j);
              Object temp = station_def.getServiceTimeDistribution(thisStation,thisClass);
              if (temp instanceof Distribution) {
                  Distribution distribution = (Distribution) temp;
                  if (!(distribution instanceof Exponential)) {
                      warnings[NO_EXP_FOUND_WARNING] = true;
                      return;
                  }
              }
          }
      }
  }
  */

  /**
   * checks for delays inside the model
   */
  /*public void checkForDelaysFoundError() {
      //get the vector of delays and servers
      Vector<Object> stations = station_def.getStationKeysNoSourceSink();
      //for each station...
      for (int i=0;i<stations.size();i++) {
          //get the type of the station
          String stationType = station_def.getStationType(stations.get(i));
          //if it is a delay there is an error
          if (stationType.equals(STATION_TYPE_DELAY)) {
              errors[DELAYS_FOUND_ERROR] = true;
              return;
          }
      }
  }
  */

  /**
   * Checks that there is at least one measure defined. If a problem is found it raises
   * to "true" the corresponding position inside the problems array.
   */
  private void checkForSimulationError() {
    Vector<Object> measures = simulation_def.getMeasureKeys();
    if (measures.size() == 0) {
      errors[SIMULATION_ERROR] = true;
    }
  }

  /**
   * Checks that each measure is defined only one time
   * <br> Fixed by Bertoli Marco to support global measures
   */
  private void checkForMeasureError() {
    Vector<Object> measures = simulation_def.getMeasureKeys();
    Vector<String> measuresAlreadyChecked = new Vector<String>(0, 1);
    for (int i = 0; i < measures.size(); i++) {
      Object thisMeasure = measures.get(i);
      String thisMeasureType = simulation_def.getMeasureType(thisMeasure);
      String thisMeasureClass;
      if (simulation_def.getMeasureClass(thisMeasure) == null) {
        thisMeasureClass = "ALL";
      } else {
        thisMeasureClass = class_def.getClassName(simulation_def.getMeasureClass(thisMeasure));
      }
      String thisMeasureStation;
      if (simulation_def.getMeasureStation(thisMeasure) == null) {
        thisMeasureStation = "ALL";
      } else {
        thisMeasureStation = station_def.getStationName(simulation_def.getMeasureStation(thisMeasure));
      }
      String thisMeasureDescription = thisMeasureType + thisMeasureClass + thisMeasureStation;
      if (!measuresAlreadyChecked.contains(thisMeasureDescription)) {
        measuresAlreadyChecked.add(thisMeasureDescription);
      } else {
        errors[DUPLICATE_MEASURE_ERROR] = true;
        redundantMeasure.add(thisMeasure);
      }
    }
  }

  /**
   * Checks that each performance index is consistent, i.e. it has no
   * 'null' field in reference station.
   * <br> Fixed by Bertoli Marco to support global measures
   */
  private void checkForInconsistentMeasureError() {
    Vector<Object> measures = simulation_def.getMeasureKeys();
    //Vector<Object> measuresAlreadyChecked = new Vector<Object>(0,1);
    for (int i = 0; i < measures.size(); i++) {
      Object thisMeasure = measures.get(i);
      String thisMeasureType = simulation_def.getMeasureType(thisMeasure);
      Object thisMeasureStationKey = simulation_def.getMeasureStation(thisMeasure);
      if ((thisMeasureType == null) || (thisMeasureStationKey == null && !simulation_def.isGlobalMeasure(thisMeasure))) {
        inconsistentMeasures.add(thisMeasure);
        errors[INCONSISTENT_MEASURE_ERROR] = true;
      }
    }
  }

    private void checkForLoadDependentRoutingError() {
        //Step 1 : Find all stations.
        for(Object stationKey : station_def.getStationKeys()) {
            //Step 2: check Routing for each class of the station
            for(Object classKey : class_def.getClassKeys()) {
                RoutingStrategy rs = (RoutingStrategy) station_def.getRoutingStrategy(stationKey, classKey);
                if(rs instanceof LoadDependentRouting){
                    List<String> errorMsgs = ((LoadDependentRouting) rs).validate();
                    if(errorMsgs != null && errorMsgs.size() > 0){
                        errors[LOAD_DEPENDENT_ROUTING_INVALID] = true;
                        HashMap innerVal = new HashMap<Object, Object>();
                        innerVal.put(stationKey, classKey);
                        invalidLoadDependentRouting.put(rs, innerVal);
                    }
                }
            }
        }
    }

  /**
   * This method is the same of checkForReferenceStationError but it checks only open classes
   */
  /*private void checkForOpenClassReferenceStationError() {
      // get the vector of the keys of the classes
      Vector<Object> classKeys = class_def.getClassKeys();
      for (int i=0; i<classKeys.size();i++) {
          //get the key at i
          Object thisKey = classKeys.get(i);
          if (class_def.getClassType(thisKey) == CommonConstants.CLASS_TYPE_OPEN) {
              //get the Reference Station of the class
              Object thisRefStation = class_def.getClassRefStation(thisKey);
              //if the class has no reference station there is a class problem
              if (thisRefStation == null) {
                  errors[OPEN_CLASS_REFERENCE_STATION_ERROR] = true;
                  openClassesWithoutRefStation.add(thisKey);
              }
          }
      }
  }*/

  /**
   * Checks if the queue strategy for each class is FCFS. Used only in toJMVA Conversion
   */
  /*private void checkForNonFCFSWarning() {
      Vector<Object> stations = station_def.getStationKeysNoSourceSink();
      Vector<Object> classes = class_def.getClassKeys();
      for (int i=0;i<stations.size();i++) {
          Object thisStation = stations.get(i);
          for (int j=0;j<classes.size();j++) {
              Object thisClass = classes.get(j);
              String qStrategy = station_def.getQueueStrategy(thisStation,thisClass);
              if (qStrategy != null) {
                  if (!qStrategy.equals(JSIMConstants.QUEUE_STRATEGY_FCFS)) {
                      nonFCFSStations.add(thisStation);
                      warnings[NON_FCFS_WARNING] = true;
                      break;
                  }
              }
          }
      }
  }
  */

  /**
   * Checks if a non random routing is used inside a station
   */
  private void checkForBCMPNonStateIndependentRoutingWarning() {
    Vector<Object> stations = station_def.getStationKeysNoSourceSink();
    Vector<Object> classes = class_def.getClassKeys();
    for (int i = 0; i < stations.size(); i++) {
      Object thisStation = stations.get(i);
      for (int j = 0; j < classes.size(); j++) {
        Object thisClass = classes.get(j);
        RoutingStrategy thisRoutingStrategy = (RoutingStrategy) station_def.getRoutingStrategy(thisStation, thisClass);
        if (thisRoutingStrategy != null) {
          if (thisRoutingStrategy.isModelStateDependent()) {
            BCMPnonStateIndependentRoutingStations.add(thisStation);
            warnings[BCMP_NON_STATE_INDEPENDENT_ROUTING_WARNING] = true;
            break;
          }
        }
      }
    }
  }

  /**
   * Explores the model, searching for routing problems for the specified close class
   * @param classKey the key of the class to be analyzed
   * @param startingStationKey the key of the station where we start analyzing the routing
   * @param alreadyVisited vector containing the keys of the already visited stations
   * @return the Vector<Object> containing the keys of the stations where the routing problem occours
   */
  private Vector<Object> exploreForRoutingProblems(Object classKey, Object startingStationKey, Vector<Object> alreadyVisited) {
    //Vector<Object> containing the keys to be returned
    Vector<Object> toBeReturned = new Vector<Object>(0, 1);
    //Vector<Object> containing the keys of the forward stations
    Vector<Object> forwardStations = station_def.getForwardConnections(startingStationKey);
    /*//if there is one only forward station ...
    if (forwardStations.size() == 1) {
        //... get the only forward station ...
        Object uniqueForwardElement = forwardStations.get(0);
        //... if it has not been explored yet ...
        if (!alreadyVisited.contains(uniqueForwardElement)) {
            //... add the element to the alreadyVisited vector ...
            alreadyVisited.add(uniqueForwardElement);
            // ... if the forward station is a Sink there is a problem, add the
            // startingStationKey to the toBeReturned vector ...
            if (station_def.getStationType(uniqueForwardElement).equals(STATION_TYPE_SINK)) toBeReturned.add(startingStationKey);
            //... else ...
            else {
                // ... explore starting from uniqueForwardElement and collect the
                // results into the temp vector ...
                Vector<Object> temp = exploreForRoutingProblems(classKey,uniqueForwardElement,alreadyVisited);
                // ... put the elements of the temp vector into the toBeReturned Vector<Object> ...
                for (int i=0; i<temp.size(); i++) {
                    toBeReturned.add(temp.get(i));
                }
            }
        }
    }
    // if there is more than one forward station ...*/
    //else {
    for (int i = 0; i < forwardStations.size(); i++) {
      // ... get the forward station at i ...
      Object thisForwardStation = forwardStations.get(i);
      //... if it has not been explored yet ...
      if (!alreadyVisited.contains(thisForwardStation)) {
        //... add the element to the alreadyVisited vector ...
        alreadyVisited.add(thisForwardStation);
        // ... get the routing strategy for the class in the starting station ...
        RoutingStrategy strategy = (RoutingStrategy) station_def.getRoutingStrategy(startingStationKey, classKey);
        // ... if thisForwardStation is a Sink ...
        if (station_def.getStationType(thisForwardStation).equals(STATION_TYPE_SINK)) {
          // ... if the routing strategy is the Probability Routing ...
          if (strategy instanceof ProbabilityRouting) {
            Map probabilities = strategy.getValues();
            // ... get the routing probability toward thisForwardStation ...
            double p = ((Double) probabilities.get(thisForwardStation)).doubleValue();
            // ... if p = 1 there is an error, put startingStationKey into the
            // toBeReturned vector ...
            if (p == 1) {
              toBeReturned.add(startingStationKey);
            }
          }
        }
        // ... else thisForwardStation isn't a Sink ...
        else {
          Vector<Object> temp;
          // ... if the routing policy is ProbabilityRouting ...
          if (strategy instanceof ProbabilityRouting) {
            Map probabilities = strategy.getValues();
            // ... get the routing probability toward thisForwardStation ...
            double p = ((Double) probabilities.get(thisForwardStation)).doubleValue();
            // ... if p != 0 start exploring from thisForwardStation and collect
            // the returned vector into temp ...
            if (p != 0) {
              temp = exploreForRoutingProblems(classKey, thisForwardStation, alreadyVisited);
            } else {
              temp = null;
            }
          } else {
            temp = exploreForRoutingProblems(classKey, thisForwardStation, alreadyVisited);
          }
          // ... if temp have been used ...
          if (temp != null) {
            // ... put its elements into the toBeReturned vector
            for (int j = 0; j < temp.size(); j++) {
              toBeReturned.add(temp.get(j));
            }
          }
        }
      }
    }
    //}
    // return the vector containing the keys of the stations where problems occour
    return toBeReturned;
  }

  /**
   * Explores the model, searching for routing problems for the specified close class
   * @param classKey the key of the class to be analyzed
   * @param startingStationKey the key of the station where we start analyzing the routing
   * @param alreadyVisited vector containing the keys of the already visited stations
   * @return the Vector<Object> containing the keys of the stations where the error occours
   */
  private Vector<Object> exploreForAllForwardStationAreSink(Object classKey, Object startingStationKey, Vector<Object> alreadyVisited) {
    boolean allSink = true;
    //Vector<Object> containing the keys to be returned
    Vector<Object> toBeReturned = new Vector<Object>(0, 1);
    //Vector<Object> containing the keys of the forward stations
    Vector<Object> forwardStations = station_def.getForwardConnections(startingStationKey);
    //Check if forwardStations are all sink
    if (forwardStations.size() == 0) {
      allSink = false;
    } else {
      for (int i = 0; i < forwardStations.size(); i++) {
        Object thisStationKey = forwardStations.get(i);
        if (!station_def.getStationType(thisStationKey).equals(STATION_TYPE_SINK)) {
          allSink = false;
        }
      }
    }
    //if forward station are all sink ...
    if (allSink) {
      //... add this startingStationKey to toBeReturned vector
      toBeReturned.add(startingStationKey);
    } else {
      for (int i = 0; i < forwardStations.size(); i++) {
        // ... get the forward station at i ...
        Object thisForwardStation = forwardStations.get(i);
        //... if it has not been explored yet ...
        if (!alreadyVisited.contains(thisForwardStation)) {
          Vector<Object> temp = null;
          //... add the element to the alreadyVisited vector ...
          alreadyVisited.add(thisForwardStation);
          // ... if thisForwardStation is not a Sink ...
          if (!station_def.getStationType(thisForwardStation).equals(STATION_TYPE_SINK)) {
            // ... get the routing strategy for the class in the starting station ...
            RoutingStrategy strategy = (RoutingStrategy) station_def.getRoutingStrategy(startingStationKey, classKey);
            if (strategy instanceof ProbabilityRouting) {
              Map probabilities = strategy.getValues();
              // ... get the routing probability toward thisForwardStation ...
              double p = ((Double) probabilities.get(thisForwardStation)).doubleValue();
              // ... if p != 0 start exploring from thisForwardStation and collect
              // the returned vector into temp ...
              if (p != 0) {
                //... start exploring from thisForwardStation
                temp = this.exploreForAllForwardStationAreSink(classKey, thisForwardStation, alreadyVisited);
              }
            } else if (strategy instanceof LoadDependentRouting) {
                            String stationName = station_def.getStationName(thisForwardStation);
                            LoadDependentRouting loadDependentRouting = (LoadDependentRouting)strategy;
              Map<Integer, LoadDependentRouting.EmpiricalEntry[]> empiricalEntries = loadDependentRouting.getEmpiricalEntries();
                            Iterator<LoadDependentRouting.EmpiricalEntry[]> rows = empiricalEntries.values().iterator();
                            Collection<LoadDependentRouting.EmpiricalEntry> allEntries = new ArrayList<LoadDependentRouting.EmpiricalEntry>(5);
                            while(rows.hasNext()){
                                LoadDependentRouting.EmpiricalEntry[] entries = rows.next();
                                allEntries.addAll(Arrays.asList(entries));
                            }
                            for(Iterator<LoadDependentRouting.EmpiricalEntry> itEntries = allEntries.iterator(); itEntries.hasNext();){
                                LoadDependentRouting.EmpiricalEntry entry = itEntries.next();
                                if(entry.getStationName().equals(stationName)){
                                    double p = entry.getProbability();
                                    if (p != 0) {
                                        //... start exploring from thisForwardStation
                                        temp = this.exploreForAllForwardStationAreSink(classKey, thisForwardStation, alreadyVisited);
                                    }
                                }
                            }
            } else {
              temp = this.exploreForAllForwardStationAreSink(classKey, thisForwardStation, alreadyVisited);
            }
          }
          //if temp != null insert its elements into toBeReturned vector
          if (temp != null) {
            for (int j = 0; j < temp.size(); j++) {
              toBeReturned.add(temp.get(j));
            }
          }
        }
      }
    }
    return toBeReturned;
  }

  /**
   * Checks for DIFFERENT_SERVICE_TIME_ERROR. It checks the mean value for each
   * service time distribution inside a station, if it hasn't a mean value the error
   * occours
   */
  /*private void checkForDifferentServiceTimesWarnings() {
      Vector<Object> stations = station_def.getStationKeysNoSourceSink();
      Vector<Object> classes = class_def.getClassKeys();
      //if no classes have been defined
      if (classes.isEmpty()) {
          //the problem can not occour -> exit
          warnings[DIFFERENT_SERVICE_TIME_WARNING] = false;
          return;
      }
      //for each server/delay...
      for (int i=0; i<stations.size();i++) {
          Object thisStation = stations.get(i);
          //get the distribution of the first class...
          Object temp = station_def.getServiceTimeDistribution(thisStation,classes.get(0));
          if (temp instanceof Distribution) {
              Distribution d = (Distribution)temp;
              //if d does not have a mean value
              if (!d.hasMean()){
                  warnings[DIFFERENT_SERVICE_TIME_WARNING] = true;
                  return;
              }
              else {
                  //else get the mean value of the distribution
                  double thisStationMean = d.getMean();
                  //for each class...
                  for (int j=0;j<classes.size();j++) {
                      Object thisClass = classes.get(j);
                      temp = station_def.getServiceTimeDistribution(thisStation,thisClass);
                      if (temp instanceof Distribution) {
                          d = (Distribution) temp;
                          //if d does not have a mean value...
                          if (!d.hasMean()) {
                              //the problem occours -> exit
                              warnings[DIFFERENT_SERVICE_TIME_WARNING] = true;
                              return;
                          }
                          else {
                              double thisMean = d.getMean();
                              //if a mean differs from the others
                              if (thisMean != thisStationMean) {
                                  //the problem occours -> exit
                                  warnings[DIFFERENT_SERVICE_TIME_WARNING] = true;
                                  return;
                              }
                          }
                      }
                  }
              }
          }
      }
  }
  */

  /**
   * To be implemented
   * @param startingStation
   * @return null
   */
  private Vector<Object> exploreForForkJoinError(Object startingStation) {
    return null;
  }

  /**
   * Checks if there are more than one sink. If a problem is found it raises
   * to "true" the corresponding position inside the warnings array.
   */
  private void checkForMoreThanOneSinkWarning() {
    int nSink = 0;
    //get the vector of the station keys
    Vector<Object> stations = station_def.getStationKeys();
    for (int i = 0; i < stations.size(); i++) {
      Object thisStationKey = stations.get(i);
      if (station_def.getStationType(thisStationKey).equals(STATION_TYPE_SINK)) {
        nSink++;
      }
    }
    if (nSink > 1) {
      warnings[MORE_THAN_ONE_SINK_WARNING] = true;
    }
  }

  /**
   * Checks if there are stations mot backward linked
   */
  private void checkForNoBacwardLinkWarning() {
    Vector<Object> stations = station_def.getStationKeys();
    for (int i = 0; i < stations.size(); i++) {
      Object thisStationKey = stations.get(i);
      if ((!station_def.getStationType(thisStationKey).equals(STATION_TYPE_SOURCE))
          && (!station_def.getStationType(thisStationKey).equals(STATION_TYPE_SINK))) {
        Vector<Object> backwardConnections = station_def.getBackwardConnections(thisStationKey);
        if (backwardConnections.size() == 0) {
          warnings[NO_BACKWARD_LINK_WARNING] = true;
          stationWithoutBackwardLinks.add(thisStationKey);
        }
      }
    }
  }

  /**
   * Checks the consistence of the parametric analysis model (if one was defined).
   * If it is inconsistent with simulation model definition it will be automatically
   * changed when possible.
   */
  private void checkForParametricAnalysisModelModifiedWarning() {
    if (simulation_def.isParametricAnalysisEnabled()) {
      ParametricAnalysisDefinition pad = simulation_def.getParametricAnalysisModel();
      int code = pad.checkCorrectness(false);
      if (code != 0) {
        if (code == 1) {
          warnings[PARAMETRIC_ANALYSIS_MODEL_MODIFIED_WARNING] = true;
        }
        if (code == 2) {
          ParametricAnalysisChecker pac = new ParametricAnalysisChecker(class_def, station_def, simulation_def);
          if (pac.canBeEnabled()) {
            //        String[] avaible = pac.getRunnableParametricAnalysis();
            //        ParametricAnalysisDefinition newPAD = ParametricAnalysisModelFactory.createParametricAnalysisModel(avaible[0],class_def,station_def,simulation_def);
            //        simulation_def.setParametricAnalysisModel(newPAD);
            warnings[PARAMETRIC_ANALYSIS_MODEL_MODIFIED_WARNING] = true;
          }
        }
      }
    }
  }

  /**
   * Checks if PA is no more avaible, but a PA model was previously defined.
   */
  private void checkForParametricAnalysisNoMoreAvaibleWarning() {
    ParametricAnalysisChecker pac = new ParametricAnalysisChecker(class_def, station_def, simulation_def);
    if ((simulation_def.isParametricAnalysisEnabled()) && (!pac.canBeEnabled())) {
      warnings[PARAMETRIC_ANALYSIS_NO_MORE_AVAIBLE_WARNING] = true;
    }
  }

  private void checkForForkWithoutJoinWarnings() {
    boolean fork = false;
    boolean join = false;
    Vector<Object> stations = station_def.getStationKeys();
    for (int i = 0; i < stations.size(); i++) {
      Object thisKey = stations.get(i);
      if (station_def.getStationType(thisKey).equals(STATION_TYPE_FORK)) {
        fork = true;
      }
      if (station_def.getStationType(thisKey).equals(STATION_TYPE_JOIN)) {
        join = true;
      }
    }
    if ((fork) && (!join)) {
      warnings[FORK_WITHOUT_JOIN_WARNING] = true;
    }
  }

  private void checkForJoinWithoutForkErrors() {
    boolean fork = false;
    boolean join = false;
    Vector<Object> stations = station_def.getStationKeys();
    for (int i = 0; i < stations.size(); i++) {
      Object thisKey = stations.get(i);
      if (station_def.getStationType(thisKey).equals(STATION_TYPE_FORK)) {
        fork = true;
      }
      if (station_def.getStationType(thisKey).equals(STATION_TYPE_JOIN)) {
        join = true;
      }
    }
    if ((!fork) && (join)) {
      errors[JOIN_WITHOUT_FORK_ERROR] = true;
    }
  }

  /**
   * To be implemented
   */
  private void checkForForkJoinRoutingError() {

  }

  private void checkForBCMPDifferentQueueingStrategyWarning() {
    Vector<Object> servers = station_def.getStationKeysServer();
    Vector<Object> classes = class_def.getClassKeys();
    for (int i = 0; i < servers.size(); i++) {
      Object thisServer = servers.get(i);
      // Processor sharing stations are okay.
      if (CommonConstants.QUEUE_STRATEGY_STATION_PS.equals(station_def.getStationQueueStrategy(thisServer))) {
        continue;
      }
      for (int j = 1; j < classes.size(); j++) {
        //Object thisClass = classes.get(j);
        String s0 = station_def.getQueueStrategy(thisServer, classes.get(j - 1));
        String s1 = station_def.getQueueStrategy(thisServer, classes.get(j));
        if (!s0.equals(s1)) {
          warnings[BCMP_DIFFERENT_QUEUEING_STRATEGIES_WARNING] = true;
          BCMPserversWithDifferentQueueStrategy.add(thisServer);
          break;
        }
      }
    }
  }

  private void checkForBCMPFcfsDifferentServiceTypesWarning() {
    Vector<Object> servers = station_def.getStationKeysServer();
    for (int i = 0; i < servers.size(); i++) {
      Object thisServer = servers.get(i);
      if (this.isAllFCFSQueueingStrategy(thisServer)) {
        if (!this.isTypeUniformServiceStrategy(thisServer)) {
          warnings[BCMP_FCFS_DIFFERENT_SERVICE_TYPES_WARNING] = true;
          BCMPserversWithDifferentServiceTypes.add(thisServer);
        }
      }
    }
  }

  private void checkForBCMPFcfsNonExponentialWarning() {
    Vector<Object> servers = station_def.getStationKeysServer();
    Vector<Object> classes = class_def.getClassKeys();
    for (int i = 0; i < servers.size(); i++) {
      Object thisServer = servers.get(i);
      // Processor sharing stations are okay.
      if (CommonConstants.QUEUE_STRATEGY_STATION_PS.equals(station_def.getStationQueueStrategy(thisServer))) {
        continue;
      }
      if ((this.isAllFCFSQueueingStrategy(thisServer)) && (this.isTypeUniformServiceStrategy(thisServer))) {
        boolean ok = true;
        for (int j = 0; j < classes.size(); j++) {
          Object thisClass = classes.get(j);
          Object service = station_def.getServiceTimeDistribution(thisServer, thisClass);
          if (service instanceof Distribution) {
            Distribution d = (Distribution) service;
            if (!d.getName().equals(CommonConstants.DISTRIBUTION_EXPONENTIAL)) {
              warnings[BCMP_FCFS_EXPONENTIAL_WARNING] = true;
              BCMPserversFCFSWithoutExponential.add(thisServer);
              break;
            }
          } else if (service instanceof LDStrategy) {
            LDStrategy ld = (LDStrategy) service;
            Object[] ranges = ld.getAllRanges();
            for (Object range : ranges) {
              Distribution d = ld.getRangeDistribution(range);
              if (!d.getName().equals(CommonConstants.DISTRIBUTION_EXPONENTIAL)) {
                warnings[BCMP_FCFS_EXPONENTIAL_WARNING] = true;
                BCMPserversFCFSWithoutExponential.add(thisServer);
                ok = false;
                break;
              }
            }
            if (!ok) {
              break;
            }
          }
        }
      }
    }
  }

  private void checkForBCMPFcfsDifferentServiceTimesWarning() {
    Vector<Object> servers = station_def.getStationKeysServer();
    Vector<Object> classes = class_def.getClassKeys();
    if ((!servers.isEmpty()) && (!classes.isEmpty())) {
      for (int i = 0; i < servers.size(); i++) {
        Object thisServer = servers.get(i);
        // Processor sharing stations are okay.
        if (CommonConstants.QUEUE_STRATEGY_STATION_PS.equals(station_def.getStationQueueStrategy(thisServer))) {
          continue;
        }
        if ((this.mustHaveSameExponentialServiceTimes(thisServer)) && (!BCMPserversFCFSWithoutExponential.contains(thisServer))) {
          Object service = station_def.getServiceTimeDistribution(thisServer, classes.get(0));
          if (service instanceof Distribution) {
            double mean = ((Distribution) service).getMean();
            for (int j = 0; j < classes.size(); j++) {
              Object thisClass = classes.get(j);
              Distribution d = (Distribution) station_def.getServiceTimeDistribution(thisServer, thisClass);
              double thisMean = d.getMean();
              if (thisMean != mean) {
                warnings[BCMP_FCFS_DIFFERENT_SERVICE_TIMES_WARNING] = true;
                BCMPFcfsServersWithDifferentServiceTimes.add(thisServer);
                break;
              }
            }
          } else if (service instanceof LDStrategy) {
            LDStrategy ld = (LDStrategy) service;
            for (int j = 0; j < classes.size(); j++) {
              Object thisClass = classes.get(j);
              LDStrategy thisLd = (LDStrategy) station_def.getServiceTimeDistribution(thisServer, thisClass);
              if (!ld.isEquivalent(thisLd)) {
                warnings[BCMP_FCFS_DIFFERENT_SERVICE_TIMES_WARNING] = true;
                BCMPFcfsServersWithDifferentServiceTimes.add(thisServer);
                break;
              }
            }
          }
        }
      }
    }
  }

  private void checkForBCMPProcessorSharingWarning() {
    //TODO:implementation
  }

  private void checkForBCMPDelayWarning() {
    Vector<Object> delays = station_def.getStationKeysDelay();
    Vector<Object> classes = class_def.getClassKeys();
    if (!delays.isEmpty()) {
      for (int i = 0; i < delays.size(); i++) {
        Object thisDelay = delays.get(i);
        for (int j = 0; j < classes.size(); j++) {
          Object thisClass = classes.get(j);
          Object service = station_def.getServiceTimeDistribution(thisDelay, thisClass);
          if (service instanceof Distribution) {
            Distribution d = (Distribution) service;
            if (d.getName().equals(CommonConstants.DISTRIBUTION_PARETO)) {
              warnings[BCMP_DELAY_WARNING] = true;
              BCMPdelaysWithNonRationalServiceDistribution.add(thisDelay);
              break;
            }
          } else if (service instanceof LDStrategy) {
            LDStrategy ld = (LDStrategy) service;
            Object[] ranges = ld.getAllRanges();
            for (Object range : ranges) {
              if (ld.getRangeDistribution(range).getName().equals(CommonConstants.DISTRIBUTION_PARETO)) {
                warnings[BCMP_DELAY_WARNING] = true;
                BCMPdelaysWithNonRationalServiceDistribution.add(thisDelay);
                break;
              }
            }
          }
        }
      }
    }
  }

  private void checkForBCMPLcfsPrWarning() {
    //TODO:implementation
  }

  private boolean isTypeUniformServiceStrategy(Object stationKey) {
    boolean value = true;
    Vector<Object> classes = class_def.getClassKeys();
    if (!classes.isEmpty()) {
      int ldFound = 0;
      int distrFound = 0;
      for (int j = 0; j < classes.size(); j++) {
        Object thisClass = classes.get(j);
        Object service = station_def.getServiceTimeDistribution(stationKey, thisClass);
        if (service instanceof LDStrategy) {
          ldFound = 1;
        } else if (service instanceof Distribution) {
          distrFound = 1;
        }
      }
      if ((ldFound * distrFound) == 1) {
        value = false;
      }
    }
    return value;
  }

  private boolean isAllFCFSQueueingStrategy(Object serverKey) {
    boolean value = true;
    Vector<Object> classes = class_def.getClassKeys();
    for (int j = 0; j < classes.size(); j++) {
      String s = station_def.getQueueStrategy(serverKey, classes.get(j));
      if (!s.equals(CommonConstants.QUEUE_STRATEGY_FCFS)) {
        value = false;
        break;
      }
    }
    return value;
  }

  private boolean mustHaveSameExponentialServiceTimes(Object station) {
    boolean result = false;
    if ((isAllFCFSQueueingStrategy(station)) && (isTypeUniformServiceStrategy(station))
        && (station_def.getStationType(station).equals(STATION_TYPE_SERVER))) {
      result = true;
    }
    return result;
  }

  /**
   * Changes all time distributions to exponential mainteining (when possible) the same mean
   * value. Since T-Student and Replayer don't have a mean value the mean value 1 is used.
   */
  /*public void changeDistributionsToExp() {
      Vector<Object> classes = class_def.getClassKeys();
      //first search for open classes with non exponential arrival time distribution
      for (int i=0; i<classes.size();i++) {
          Object thisKey = classes.get(i);
          //if this class is an open class
          if (class_def.getClassType(thisKey) == CLASS_TYPE_OPEN) {
              //get the distribution for this open class
              Distribution distribution = (Distribution)class_def.getClassDistribution(thisKey);
              if ((distribution != null)&&(!(distribution instanceof Exponential))) {
                  double meanToSet;
                  //if does not have a mean value
                  if (!distribution.hasMean()) {
                      //set the mean to 1
                      meanToSet = 1;
                  }
                  //else get the mean from the old distribution
                  else {
                      meanToSet = distribution.getMean();
                  }
                  //create a new exponential distribution
                  Exponential newDistribution = new Exponential();
                  //with meanToSet as mean value
                  newDistribution.setMean(meanToSet);
                  //set the new distribution
                  class_def.setClassDistribution(newDistribution,thisKey);
              }
          }
      }
      //than search for non exponential service time distribution
      Vector<Object> stations = station_def.getStationKeys();
      //Vector<Object> serverDelay = new Vector<Object>(0,1);
      for (int i=0; i<stations.size();i++) {
          //get the station at i
          Object thisStation = stations.get(i);
          for (int j=0; j<classes.size();j++) {
              //get the class at j
              Object thisClass = classes.get(j);
              //get the service time distribution for thisClass at thisStation
              Object temp = station_def.getServiceTimeDistribution(thisStation,thisClass);
              if (temp instanceof Distribution) {
                  Distribution distribution = (Distribution) temp;
                  if (!(distribution instanceof Exponential)) {
                      double meanToSet;
                      //if the distribution is a Replayer or a T-Student
                      if (!distribution.hasMean()){
                          //set the mean to 1
                          meanToSet = 1;
                      }
                      //else get the mean from the old distribution
                      else {
                          meanToSet = distribution.getMean();
                      }
                      //create a new exponential distribution
                      Exponential newDistribution = new Exponential();
                      //with meanToSet as mean value
                      newDistribution.setMean(meanToSet);
                      //set the new distribution
                      station_def.setServiceTimeDistribution(thisStation,thisClass,newDistribution);
                  }
              }
          }
      }
  }

  public void flattenServiceTimes() {
      Vector<Object> classes = class_def.getClassKeys();
      //than search for non exponential service time distribution
      Vector<Object> stations = station_def.getStationKeysNoSourceSink();
      for (int i=0; i<stations.size();i++) {
          //get the station at i
          Object thisStation = stations.get(i);
          double minMean = Double.MAX_VALUE;
          boolean atLeastOneValidDistribution = false;
          for (int j=0; j<classes.size();j++) {
              //get the class at j
              Object thisClass = classes.get(j);
              //get the service time distribution for thisClass at thisStation
              Object temp = station_def.getServiceTimeDistribution(thisStation,thisClass);
              if (temp instanceof Distribution) {
                  Distribution distribution = (Distribution) temp;
                  if (distribution.hasMean()) {
                      double thisMean = distribution.getMean();
                      if (thisMean < minMean) minMean = thisMean;
                      atLeastOneValidDistribution = true;
                  }
                  else {
                      Exponential exp = new Exponential();
                      station_def.setServiceTimeDistribution(thisStation,thisClass,exp);
                  }
              }
          }
          //if all service time distributions doesn't have a mean value
          if (!atLeastOneValidDistribution) {
              minMean = 1;
          }
          for (int j=0; j<classes.size();j++) {
              //get the class at j
              Object thisClass = classes.get(j);
              //get the service time distribution for thisClass at thisStation
              Object temp = station_def.getServiceTimeDistribution(thisStation,thisClass);
              if (temp instanceof Distribution)  {
                  Distribution distribution = (Distribution) temp;
                  //set the mean value to minMean
                  distribution.setMean(minMean);
              }
          }
      }
  }



  /**
   * Deletes all measure already defined
   */
  public void deleteRedundantMeasure() {
    for (int i = 0; i < redundantMeasure.size(); i++) {
      Object thisRedundantMeasure = redundantMeasure.get(i);
      simulation_def.removeMeasure(thisRedundantMeasure);
    }
  }

  /**
   * Deletes all empty blocking regions
   * <br>Author: Bertoli Marco
   */
  public void deleteEmptyBlockingRegions() {
    for (int i = 0; i < emptyBlockingRegions.size(); i++) {
      blocking_def.deleteBlockingRegion(emptyBlockingRegions.get(i));
    }
  }

  /**
   * Converts all non FCFS queueing strategies to FCFS (only used in JMVA conversion)
   */
  /*public void flattenQueueingStrategies(Object serverKey) {
      Vector<Object> classes = class_def.getClassKeys();

      //initialize the hashmap containing the occourrences for each
      //queueing strategy
      HashMap strategiesOcc = new HashMap(0,1);
      Vector<Object> strategies = new Vector<Object>(0,1);
      for (int i=0;i<classes.size();i++) {
          Object thisClass = classes.get(i);
          String thisStrategy = station_def.getQueueStrategy(serverKey,thisClass);
          Object occ = strategiesOcc.get(thisStrategy);
          if (occ == null) {
              strategiesOcc.put(thisStrategy,new Integer(1));
              strategies.add(thisStrategy);
          }
          else {
              int prevOcc = ((Integer)strategiesOcc.get(thisStrategy)).intValue();
              int newOcc = prevOcc+1;
              strategiesOcc.put(thisStrategy,new Integer(newOcc));
          }
      }

      //Find the q. strategy with more occorrences
      int max = Integer.MIN_VALUE;
      int indexOfMax = -1;
      for (int i=0;i<strategies.size();i++) {
          String thisStrategy = (String)strategies.get(i);
          int thisOcc = ((Integer)strategiesOcc.get(thisStrategy)).intValue();
          if (thisOcc > max) {
              max = thisOcc;
              indexOfMax = i;
          }
      }
      String strategyToSet = (String)strategies.get(indexOfMax);

      //Set the queue strategy for each class
      for (int i=0;i<classes.size();i++) {
          Object thisClass = classes.get(i);
          station_def.setQueueStrategy(serverKey,thisClass,strategyToSet);
      }

  }

  /**
   * Converts all state dependent routing strategies to Random Routing
   * (only used in JMVA conversion)
   */
  public void setAllStateDependentRoutingStrategyToRandomRouting() {
    Vector<Object> classes = class_def.getClassKeys();
    for (int i = 0; i < BCMPnonStateIndependentRoutingStations.size(); i++) {
      Object thisStation = BCMPnonStateIndependentRoutingStations.get(i);
      for (int j = 0; j < classes.size(); j++) {
        Object thisClass = classes.get(j);
        RoutingStrategy rs = (RoutingStrategy) station_def.getRoutingStrategy(thisStation, thisClass);
        if (rs.isModelStateDependent()) {
          station_def.setRoutingStrategy(thisStation, thisClass, new RandomRouting());
        }
      }
    }
  }
 
  private void checkForSinkPerfIndicesWithNoSink() {
    boolean sinkFound = false;
    Vector<Object> stations = station_def.getStationKeys();
    for (int i = 0; i < stations.size(); i++) {
      Object thisStationKey = stations.get(i);
      if (station_def.getStationType(thisStationKey).equals(STATION_TYPE_SINK)) {
        sinkFound = true;
        break;
      }
    }
    Vector<Object> measures = simulation_def.getMeasureKeys();
    for (int i = 0; i < measures.size(); i++) {
      Object thisMeasure = measures.get(i);
      String thisMeasureType = simulation_def.getMeasureType(thisMeasure);
      boolean sinkPerfIndex = false;
      sinkPerfIndex = (thisMeasureType.equalsIgnoreCase(SimulationDefinition.MEASURE_R_PER_SINK)
          ||thisMeasureType.equalsIgnoreCase(SimulationDefinition.MEASURE_X_PER_SINK)) ? true : false;
      if(sinkPerfIndex && !sinkFound){
        errors[SINK_PERF_IND_WITH_NO_SINK_ERROR] = true;
        break;
      }
    }   
  }
 
  public void checkForSinkPerfIndicesWithClosedClass(){
    Vector<Object> closedClassKeys = class_def.getClosedClassKeys();
    Vector<Object> measures = simulation_def.getMeasureKeys();
    for (int i = 0; i < measures.size(); i++) {
      Object thisMeasure = measures.get(i);
      boolean sinkPerfIndex = false;
      Object measureClassKey = simulation_def.getMeasureClass(thisMeasure);
      String thisMeasureType = simulation_def.getMeasureType(thisMeasure);
      sinkPerfIndex = (thisMeasureType.equalsIgnoreCase(SimulationDefinition.MEASURE_R_PER_SINK)
          ||thisMeasureType.equalsIgnoreCase(SimulationDefinition.MEASURE_X_PER_SINK)) ? true : false;
      if(sinkPerfIndex && closedClassKeys.contains(measureClassKey)){
        errors[SINK_PERF_WITH_CLOSED_CLASS_ERROR] = true;
        break;
      }
    }   
  }
 
  public void checkForSinkProbabilityUpdateWarning(){
    if(station_def.isSinkProbabilityUpdated()){
      warnings[SINK_PROBABILITY_UPDATE_WARNING] = true;
      station_def.setSinkProbabilityUpdatedVar(false);//reset the value.
    }
  }

  /**
   * It checks if exist some class_switch components
   * between a fork and a join.
   */
  public void checkForCsBetweenForkJoin() {
    for(int i = 0; i < station_def.getStationKeys().size(); i++) {
      Object stationKey = station_def.getStationKeys().get(i);
      if(!station_def.getStationType(stationKey).equals(STATION_TYPE_FORK)) {
        continue;
      }
      Object tmp = checkForCsBetweenForkJoinHelper(stationKey, stationKey, false, true, null);
      if(tmp!=null) {
        errors[CS_BETWEEN_FORK_JOIN] = true;
        csBetweenForkJoin.add(tmp);
      }
    }
  }
 
  /**
   * Helper of checkForCsBetweenForkJoin.
   * It uses recursion
   * @param start
   *       the station from which the check begins.
   *       It is used to prevent infinite loop.
   * @param curr  the current station we are analyzing
   * @param foundedCS
   *       True if in the path between start  and current
   *       exist some class_switch components.
   * @param firstInvokation
   *       True if it is the first time you invoke this
   *       method.
   * @param wrongCs
   *       If foundedCS is equals to true, this parameter
   *       contains the pointer to the class_switch components
   *       found.
   * @return It returns the pointer to the class_switch components
   *       founded between start and a join, it returns null
   *       if such components does not exist.
   *    
   */
  private Object checkForCsBetweenForkJoinHelper(Object start, Object curr, boolean foundedCS, boolean firstInvokation, Object wrongCs) {
    boolean foundedCSCopy =  foundedCS;
    Object wrongCsCopy = wrongCs;
    //Exit conditions
    if(curr != null) {
      if(station_def.getStationType(curr).equals(STATION_TYPE_CLASSSWITCH)) {
        foundedCSCopy = true;
        wrongCsCopy = curr;
      }
      if(station_def.getStationType(curr).equals(STATION_TYPE_JOIN) && foundedCS)//Error
        return wrongCsCopy;
      if(station_def.getStationType(curr).equals(STATION_TYPE_JOIN) && !foundedCS)//Everything ok
        return null;
      if(curr.equals(start) && !firstInvokation)
        return null;
    }
    //Recursion
    Vector<Object> forward = station_def.getForwardConnections(curr);
    for(int i = 0; i < forward.size(); i++) {
      Object forwardStation = forward.get(i);
      Object tmp = checkForCsBetweenForkJoinHelper(start, forwardStation, foundedCSCopy, false, wrongCsCopy);
      if(tmp != null) {
        return tmp;
      }
    }
    return null;
  }
 
  /**
   * It checks if exist some class_switch components
   * followed by a queue implementing the BAS strategy.
   */
  public void checkForCsFollowedByBAS() {
    for(int i = 0; i < station_def.getStationKeys().size(); i++) {
      Object stationKey = station_def.getStationKeys().get(i);
      if(!station_def.getStationType(stationKey).equals(STATION_TYPE_CLASSSWITCH)) {
        continue;
      }
      Vector<Object> forward = station_def.getForwardConnections(stationKey);
      for(int j = 0; j < forward.size(); j++) {
        Object forwardStation = forward.get(j);
        for(int k = 0; k < class_def.getClassKeys().size(); k++) {
          String queueStrat = station_def.getDropRule(forwardStation, class_def.getClassKeys().get(k));
          if(queueStrat.equals( CommonConstants.FINITE_BLOCK)) {
            errors[CS_FOLLOWED_BY_A_BAS] = true;
            csFollowedByBas.add(stationKey);
          }
        }
      }
    }
  }
 
  /**
   * It checks if exist some class_switch components
   * with a wrong matrix (e.g. some rows do not sum
   * to a value grater or equals to one.)
   */
  public void checkForCsMatrixProbabilities() {
    for(int i = 0; i < station_def.getStationKeys().size(); i++) {
      Object stationKey = station_def.getStationKeys().get(i);
      if(!station_def.getStationType(stationKey).equals(STATION_TYPE_CLASSSWITCH)) {
        continue;
      }
      for(int j = 0; j < class_def.getClassKeys().size(); j++) {
        float row = 0;
        for(int k = 0; k < class_def.getClassKeys().size(); k++) {
          row += station_def.getClassSwitchMatrix(stationKey,
              class_def.getClassKeys().get(j), class_def.getClassKeys().get(k));
        }
        if(row < 1) {
          errors[CS_MATRIX_HAS_ROWS_LESS_THAN_ONE] = true;
          csWithWrongMatrix.add(stationKey);
          return;
        }
      }
    }
  }
 
  public boolean isThereSinkProbabilityUpdateWarning(){
    return warnings[SINK_PROBABILITY_UPDATE_WARNING];
  }
}
TOP

Related Classes of jmt.gui.common.controller.ModelChecker

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.