/**
   * Creates instances of CloudSim's Cloudlet class from a customer's utilization profile.
   *
   * @param ugr the utilization profile.
   * @param brokerId the id of the broker that owns the cloudlets.
   * @param numOfVms the number of virtual machines.
   * @return a list of Cloudlet instances.
   * @since 1.0
   */
  static List<Cloudlet> createCloudlets(UtilizationProfile ugr, int brokerId, long numOfVms)
      throws IOException, ServiceDeniedException {
    List<Cloudlet> list = new ArrayList<Cloudlet>();

    for (int i = 0; i < numOfVms; i++) {

      Optional<UtilizationModel> cpu =
          UTILIZATION_MODEL.getExtensionInstanceByName(ugr.getUtilizationModelCpuAlias());

      if (!cpu.isPresent()) {
        Dialog.showErrorMessage(
            null,
            format(
                "Error on loading the CPU utilization model [%s]",
                ugr.getUtilizationModelCpuAlias()));
        return null;
      }

      Optional<UtilizationModel> ram =
          UTILIZATION_MODEL.getExtensionInstanceByName(ugr.getUtilizationModelRamAlias());

      if (!ram.isPresent()) {
        Dialog.showErrorMessage(
            null,
            format(
                "Error on loading the RAM utilization model [%s]",
                ugr.getUtilizationModelRamAlias()));
        return null;
      }

      Optional<UtilizationModel> bw =
          UTILIZATION_MODEL.getExtensionInstanceByName(ugr.getUtilizationModelBwAlias());

      if (!bw.isPresent()) {
        Dialog.showErrorMessage(
            null,
            format(
                "Error on loading the bandwidth utilization model [%s]",
                ugr.getUtilizationModelBwAlias()));
        return null;
      }

      Cloudlet cloudlet =
          new Cloudlet(
              i,
              (long) ((long) ugr.getLength() * RandomNumberGenerator.getRandomNumbers(1).get(0)),
              ugr.getCloudletsPesNumber(),
              ugr.getFileSize(),
              ugr.getOutputSize(),
              cpu.get(),
              ram.get(),
              bw.get());

      cloudlet.setUserId(brokerId);
      cloudlet.setVmId(i);
      list.add(cloudlet);
    }

    return list;
  }
  /**
   * Creates instances of CloudSim's VM class from a list of virtual machine registers.
   *
   * @param vmList a list of virtual machine registers.
   * @param brokerId the id of the broker that owns the virtual machines.
   * @return a list of VM instances.
   * @since 1.0
   */
  static List<Vm> createVms(List<VirtualMachineRegistry> vmList, int brokerId) {
    List<Vm> list = new ArrayList<Vm>();

    int vmId = 0;
    for (VirtualMachineRegistry vmr : vmList) {
      for (int n = 0; n < vmr.getAmount(); n++) {
        Optional<CloudletScheduler> cs =
            CLOUDLET_SCHEDULER.getExtensionInstanceByName(
                vmr.getSchedulingPolicyAlias(), vmr.getMips(), vmr.getPesNumber());

        if (!cs.isPresent()) {
          Dialog.showErrorMessage(
              null,
              format(
                  "Error on loading the cloudlet scheduler [%s]", vmr.getSchedulingPolicyAlias()));
          return null;
        }

        list.add(
            new Vm(
                vmId,
                brokerId,
                vmr.getMips(),
                vmr.getPesNumber(),
                vmr.getRam(),
                vmr.getBw(),
                vmr.getSize(),
                vmr.getVmm(),
                cs.get()));
        vmId++;
      }
    }
    return list;
  }
  /**
   * Creates instances of CloudSim's PowerDatacenter class from a list of datacenter registries.
   *
   * @param dcrList a list of datacenter registries.
   * @return a map containing names of datacenters as keys and PowerDatacenter instances as values.
   * @since 1.0
   */
  static HashMap<String, PowerDatacenter> createDatacenters() {
    List<DatacenterRegistry> dcrList = DatacenterRegistryBusiness.getListOfDatacenters();
    HashMap<String, PowerDatacenter> map = new HashMap<String, PowerDatacenter>();

    for (DatacenterRegistry dcr : dcrList) {
      List<PowerHost> hostList = createHosts(dcr.getHostList());
      if (hostList == null) {
        return null;
      }

      DatacenterCharacteristics chars =
          new DatacenterCharacteristics(
              dcr.getArchitecture(),
              dcr.getOs(),
              dcr.getVmm(),
              hostList,
              dcr.getTimeZone(),
              dcr.getCostPerSec(),
              dcr.getCostPerMem(),
              dcr.getCostPerStorage(),
              dcr.getCostPerBw());

      LinkedList<Storage> storageList = createStorageList(dcr.getSanList());

      try {

        Optional<VmAllocationPolicy> allocationPolicy =
            VM_ALLOCATION_POLICY.getExtensionInstanceByName(
                dcr.getAllocationPolicyAlias(), hostList, dcr);

        if (!allocationPolicy.isPresent()) {
          Dialog.showErrorMessage(
              null,
              format(
                  "Error on loading the allocation policy [%s]", dcr.getAllocationPolicyAlias()));
          return null;
        }

        PowerDatacenter newDC =
            new PowerDatacenter(
                dcr.getName(),
                chars,
                allocationPolicy.get(),
                storageList,
                dcr.getSchedulingInterval(),
                dcr.getMonitoringInterval());

        newDC.setDisableMigrations(!dcr.isVmMigration());

        map.put(dcr.getName(), newDC);
      } catch (Exception ex) {
        LOG.error("Error on creating data centers. Error message: [{}]", ex.getMessage(), ex);
      }
    }

    return map;
  }
  /**
   * Creates instances of CloudSim's DatacenterBroker class from a list of customer registers.
   *
   * @param customerList a list of customer instances.
   * @return a map containing names of customers as keys and DatacenterBroker instances as values.
   * @since 1.0
   */
  static HashMap<String, DatacenterBroker> createBrokers() {
    List<CustomerRegistry> customerList = CustomerRegistryBusiness.getListOfCustomers();
    HashMap<String, DatacenterBroker> map = new HashMap<String, DatacenterBroker>();

    try {
      for (CustomerRegistry cr : customerList) {
        UtilizationProfile up = cr.getUtilizationProfile();
        String name = cr.getName();

        Optional<DatacenterBroker> broker =
            DATACENTER_BROKER.getExtensionInstanceByName(up.getBrokerPolicyAlias(), name);

        if (!broker.isPresent()) {
          Dialog.showErrorMessage(
              null, format("Error on loading datacenter broker [%s]", up.getBrokerPolicyAlias()));
          return null;
        }

        int brokerId = broker.get().getId();

        List<Vm> vmList = createVms(cr.getVmList(), brokerId);

        if (vmList == null) {
          return null;
        }

        broker.get().submitVmList(vmList);

        List<Cloudlet> cloudletList =
            createCloudlets(up, brokerId, new CustomerRegistryDAO().getNumOfVms(cr.getId()));

        if (cloudletList == null) {
          return null;
        }

        broker.get().submitCloudletList(cloudletList);
        map.put(cr.getName(), broker.get());
      }
    } catch (IOException | ServiceDeniedException ex) {
      LOG.error(ex.getMessage(), ex);
    }

    return map;
  }
  /**
   * Creates instances of CloudSim's PowerPe class from a host registry.
   *
   * @param hr a host registry.
   * @return a list of PowerPe instances.
   * @since 1.0
   */
  static List<Pe> createPes(HostRegistry hr) {
    List<Pe> list = new ArrayList<Pe>();

    for (int i = 0; i < hr.getNumOfPes(); i++) {

      Optional<PeProvisioner> pp =
          PE_PROVISIONER.getExtensionInstanceByName(hr.getPeProvisionerAlias(), hr.getMipsPerPe());

      if (!pp.isPresent()) {
        Dialog.showErrorMessage(
            null,
            format("Error on loading the PE provisioning policy [%s]", hr.getPeProvisionerAlias()));
        return null;
      }

      list.add(new Pe(i, pp.get()));
    }

    return list;
  }
  /**
   * Creates instances of CloudSim's PowerHost class from a list of host registers.
   *
   * @param hostList a list of datacenter registers
   * @return a list of PowerHost instances.
   * @since 1.0
   */
  static List<PowerHost> createHosts(final List<HostRegistry> hostList) {
    final List<PowerHost> list = new ArrayList<PowerHost>();

    int i = 0;

    for (HostRegistry hr : hostList) {
      for (int n = 0; n < hr.getAmount(); n++) {
        List<Pe> peList = createPes(hr);

        if (peList == null) {
          return null;
        }

        Optional<RamProvisioner> rp =
            RAM_PROVISIONER.getExtensionInstanceByName(hr.getRamProvisionerAlias(), hr.getRam());

        if (!rp.isPresent()) {
          Dialog.showErrorMessage(
              null,
              format("Error on loading the RAM provisioner [%s]", hr.getRamProvisionerAlias()));
          return null;
        }

        Optional<BwProvisioner> bp =
            BW_PROVISIONER.getExtensionInstanceByName(
                hr.getBwProvisionerAlias(), (long) hr.getBw());

        if (!bp.isPresent()) {
          Dialog.showErrorMessage(
              null,
              format(
                  "Error on loading the bandwidth provisioner [%s]", hr.getBwProvisionerAlias()));
          return null;
        }

        Optional<VmScheduler> vs =
            VM_SCHEDULER.getExtensionInstanceByName(hr.getSchedulingPolicyAlias(), peList);

        if (!vs.isPresent()) {
          Dialog.showErrorMessage(
              null,
              format(
                  "Error on loading the VM scheduling policy [%s]", hr.getSchedulingPolicyAlias()));
          return null;
        }

        Optional<PowerModel> pm =
            POWER_MODEL.getExtensionInstanceByName(
                hr.getPowerModelAlias(), hr.getMaxPower(), hr.getStaticPowerPercent());

        if (!pm.isPresent()) {
          Dialog.showErrorMessage(
              null, format("Error on loading the power model [%s]", hr.getPowerModelAlias()));
          return null;
        }

        list.add(new PowerHost(i, rp.get(), bp.get(), hr.getStorage(), peList, vs.get(), pm.get()));
        i++;
      }
    }

    return list;
  }