/**
  * returns initial mode as true if it is a SOM without modes ("no Modes" aka NORMAL_SOM_NME) or if
  * all of the modes are initial mode
  */
 @Override
 public final boolean isInitial() {
   if (isInitial == null) {
     Boolean value = Boolean.TRUE;
     final Iterator<ModeInstance> i = getCurrentModes().iterator();
     // Is the list empty?
     if (!i.hasNext()) {
       // The SOM has no modes. Check to make sure, it is the only SOM, i.e., "No Modes". Otherwise
       // it is not initial
       if (((SystemInstance) eContainer()).getSystemOperationModes().size() != 1) {
         value = Boolean.FALSE;
       }
     } else {
       while (i.hasNext()) {
         final ModeInstance mi = i.next();
         final Mode m = mi.getMode();
         if (!m.isInitial()) {
           value = Boolean.FALSE;
           break;
         }
       }
     }
     isInitial = value;
   }
   return isInitial.booleanValue();
 }
 List<String> getProcessModesIdentifiers(ProcessSubcomponent ps) {
   List<String> result = new ArrayList<String>();
   ProcessImplementation pi = (ProcessImplementation) ps.getSubcomponentType();
   List<Mode> modeList = pi.getOwnedModes();
   if (modeList.isEmpty()) result.add(MAIN_APP_MODE);
   for (Mode m : modeList) {
     if (m.isInitial()) result.add(m.getName());
   }
   for (Mode m : modeList) {
     if (!m.isInitial()) result.add(m.getName());
   }
   return result;
 }
  /**
   * Génération du code OIL d'un thread.
   *
   * @param ps Le processeur conteannt les threads.
   * @param thread L'AST du thread.
   * @param counterName Le nom du compteur sur lequel la tâche se synchronise
   */
  private void genTask(ProcessSubcomponent ps, ThreadSubcomponent thread, String counterName) {

    final Cpu cpu = oil.getCpu();
    final Counter counter = cpu.getCounter();
    final Os os = cpu.getOs();

    /*
     * If one thread/device contains Initialize_Entrypoint STARTUPHOOK =
     * true
     */
    if (os.getStartupHook() == false) {
      if (PropertyUtils.findPropertyAssociation("Initialize_Entrypoint", thread) != null)
        os.setStartupHook(true);
    }

    /*
     * If one thread/device contains Finalize_Entrypoint SHUTDOWNHOOK = true
     */
    if (os.getShutdownHook() == false) {
      if (PropertyUtils.findPropertyAssociation("Finalize_Entrypoint", thread) != null)
        os.setShutdownHook(true);
    }

    /* Begin task */

    Task task = new Task();
    Schedule schedule;
    Long stackSize = PropertyUtils.getIntValue(thread, "Stack_Size");
    Long priority = PropertyUtils.getIntValue(thread, "Priority");

    if (priority == null) {
      String errMsg = "cannot fetch Priority for \'" + thread.getName() + '\'';
      _LOGGER.error(errMsg);
      ServiceProvider.SYS_ERR_REP.error(errMsg, true);
      priority = -1l;
    }

    if (stackSize == null) {
      stackSize = THREAD_STACKSIZE;
      String msg = "set default stack size for \'" + thread.getName() + '\'';
      _LOGGER.warn(msg);
      ServiceProvider.SYS_ERR_REP.warning(msg, true);
    }

    Boolean scheduler = PropertyUtils.getBooleanValue(ps, "Preemptive_Scheduler");
    if (scheduler == null) {
      schedule = Schedule.FULL;
      String msg = "set default scheduler for \'" + thread.getName() + '\'';
      _LOGGER.warn(msg);
      ServiceProvider.SYS_ERR_REP.warning(msg, true);
    } else {
      if (scheduler) schedule = Schedule.FULL;
      else schedule = Schedule.NON;
    }

    task.setName(thread.getName());
    task.setPriority(priority.intValue());
    task.setActivation(THREAD_ACTIVATION);

    task.setSchedule(schedule);
    task.setStacksize(stackSize.intValue());

    ThreadImplementation ti = (ThreadImplementation) thread.getSubcomponentType();
    ThreadType tt = (ThreadType) ti.getType();
    for (DataAccess da : this.dataAccessMapping.keySet()) {
      for (DataAccess tda : tt.getOwnedDataAccesses()) {
        if (tda.equals(da)) {
          task.addResource(this.dataAccessMapping.get(tda));
          if (da.getDataFeatureClassifier().getName().equalsIgnoreCase(EVENTDATA_PORT_TYPE))
            task.addEvent(this.dataAccessMapping.get(da));
        }
      }
    }

    /* End task */

    /*
     * Generate alarme associated to periodic tasks
     */
    {
      String dispatchProtocol = PropertyUtils.getEnumValue(thread, "Dispatch_Protocol");

      if ("Periodic".equals(dispatchProtocol)) {

        /* Begin Alarm */

        Long period = PropertyUtils.getIntValue(thread, "Period");
        if (period == null) {
          String errMsg = "cannot fetch Period for " + thread.getName();
          _LOGGER.error(errMsg);
          ServiceProvider.SYS_ERR_REP.error(errMsg, true);
          period = -1l;
        }

        int alarmTime = 0;
        try {
          alarmTime = 1;
        } catch (Exception exc) {
        }

        List<String> inModeIdList = new ArrayList<String>();
        ProcessImplementation pi = (ProcessImplementation) ps.getSubcomponentType();
        if (pi.getOwnedModes().isEmpty()) inModeIdList.add(MAIN_APP_MODE);
        else {
          if (thread.getAllInModes().isEmpty()) {
            for (Mode m : pi.getOwnedModes()) {
              inModeIdList.add(m.getName());
            }
          } else {
            for (Mode m : thread.getAllInModes()) {
              inModeIdList.add(m.getName());
            }
          }
        }

        Alarm alarm = new Alarm(counter, task, cpu, inModeIdList);

        alarm.setName("wakeUp" + thread.getName());
        alarm.setAction(Action.ACTIVATETASK);
        alarm.setAutostart(true);
        alarm.setAlarmTime(alarmTime);
        alarm.setCycleTime(period.intValue());

        task.setAutostart(false);

        cpu.addPeriodicTask(new PeriodicTask(task, alarm));
        /* End Alarm */
      } else {
        task.setAutostart(true);
        cpu.addTask(task);
      }
    }
  }
  /**
   * check the load from components bound to the given processor The components can be threads or
   * higher level components.
   *
   * @param curProcessor Component Instance of processor
   */
  protected void checkProcessorLoad(ComponentInstance curProcessor, final SystemOperationMode som) {
    boolean isCPUActive;

    if (curProcessor.getSubcomponent().getAllInModes().size() == 0) {
      isCPUActive = true;
    } else {
      isCPUActive = false;

      for (Mode mi : curProcessor.getSubcomponent().getAllInModes()) {
        // OsateDebug.osateDebug("somName=" + somName + " mi=" + mi);
        if (som.getName().equalsIgnoreCase(mi.getName())) {
          //	OsateDebug.osateDebug("cpu " + curProcessor.getName() +  "is active for mode" +
          // somName);
          isCPUActive = true;
        }
      }
    }

    if (isCPUActive == false) {
      return;
    }

    UnitLiteral mipsliteral = GetProperties.getMIPSUnitLiteral(curProcessor);
    double MIPScapacity = GetProperties.getMIPSCapacityInMIPS(curProcessor, 0.0);
    if (MIPScapacity == 0 && InstanceModelUtil.isVirtualProcessor(curProcessor)) {
      MIPScapacity = GetProperties.getMIPSBudgetInMIPS(curProcessor);
    }
    long timeBefore = System.currentTimeMillis();
    OsateDebug.osateDebug(
        "[CPU] before get sw comps (CPU="
            + curProcessor.getName()
            + ",cat="
            + curProcessor.getComponentClassifier().getCategory().getName()
            + ")");
    EList<ComponentInstance> boundComponents = InstanceModelUtil.getBoundSWComponents(curProcessor);
    long timeAfter = System.currentTimeMillis();
    long period = timeAfter - timeBefore;
    OsateDebug.osateDebug("[CPU] after get sw comps, time taken=" + period + "ms");

    if (boundComponents.size() == 0 && MIPScapacity > 0) {
      errManager.infoSummary(
          curProcessor,
          som.getName(),
          "No application components bound to "
              + curProcessor.getComponentInstancePath()
              + " with MIPS capacity "
              + GetProperties.toStringScaled(MIPScapacity, mipsliteral));
      return;
    }
    if (MIPScapacity == 0 && InstanceModelUtil.isVirtualProcessor(curProcessor)) {
      errManager.warningSummary(
          curProcessor,
          som.getName(),
          "Virtual processor "
              + curProcessor.getComponentInstancePath()
              + " has no MIPS capacity or budget.");
      return;
    }
    if (MIPScapacity == 0 && InstanceModelUtil.isProcessor(curProcessor)) {
      errManager.errorSummary(
          curProcessor,
          som.getName(),
          "Processor "
              + curProcessor.getComponentInstancePath()
              + " has no MIPS capacity but has bound components.");
    }
    if (InstanceModelUtil.isVirtualProcessor(curProcessor)) {
      logHeader(
          "\n\nDetailed Workload Report for Virtual Processor "
              + curProcessor.getComponentInstancePath()
              + " with Capacity "
              + GetProperties.toStringScaled(MIPScapacity, mipsliteral)
              + "\n\nComponent,Budget,Actual");
    } else {
      logHeader(
          "\n\nDetailed Workload Report for Processor "
              + curProcessor.getComponentInstancePath()
              + " with Capacity "
              + GetProperties.toStringScaled(MIPScapacity, mipsliteral)
              + "\n\nComponent,Budget,Actual");
    }
    double totalMIPS = 0.0;
    for (Iterator<ComponentInstance> it = boundComponents.iterator(); it.hasNext(); ) {
      ComponentInstance bci = (ComponentInstance) it.next();
      boolean isComponentActive;

      if ((som == null) || (bci.getSubcomponent().getAllInModes().size() == 0)) {
        isComponentActive = true;
      } else {
        isComponentActive = false;
        for (Mode mi : bci.getSubcomponent().getAllInModes()) {
          // OsateDebug.osateDebug("somName=" + somName + " mi=" + mi);
          if (som.getName().equalsIgnoreCase(mi.getName())) {
            //	OsateDebug.osateDebug("cpu " + curProcessor.getName() +  "is active for mode" +
            // somName);
            isComponentActive = true;
          }
        }
      }

      if (isComponentActive == true) {
        double actualmips = sumBudgets(bci, ResourceKind.MIPS, mipsliteral, true, som, "");
        totalMIPS += actualmips;
      }
    }
    logHeader("Total," + GetProperties.toStringScaled(totalMIPS, mipsliteral));
    if (totalMIPS > MIPScapacity) {
      errManager.errorSummary(
          curProcessor,
          som.getName(),
          "Total MIPS "
              + GetProperties.toStringScaled(totalMIPS, mipsliteral)
              + " of bound tasks exceeds MIPS capacity "
              + GetProperties.toStringScaled(MIPScapacity, mipsliteral)
              + " of "
              + curProcessor.getComponentInstancePath());
    } else if (totalMIPS == 0.0) {
      errManager.warningSummary(curProcessor, som.getName(), "Bound app's have no MIPS budget.");
    } else {
      errManager.infoSummary(
          curProcessor,
          som.getName(),
          "Total MIPS "
              + GetProperties.toStringScaled(totalMIPS, mipsliteral)
              + " of bound tasks within "
              + "MIPS capacity "
              + GetProperties.toStringScaled(MIPScapacity, mipsliteral)
              + " of "
              + curProcessor.getComponentInstancePath());
    }
  }