/**
   *
   * <!-- begin-user-doc -->
   * This method goes over a provided SEType (config file) entities with matching criteria defined
   * in config file. It goes over the attributes required to report on and collects min,max and avg
   * into extension objects for commodity and service entity.
   *
   * <p>Every hour it creates a list of {@link ReportingRecord} objects with data and returns this
   * list.
   * <!-- end-user-doc -->
   *
   * @param hourChanged true if the hour changed from the previous gathering of values.
   * @generated NOT
   */
  @Override
  public EList<ReportingRecord> getReportingRecordList(boolean hourChanged) {
    EList<ReportingRecord> returnList = new BasicEList<ReportingRecord>();
    long hourlyTimeStamp = 0l;
    try {
      RepositoryRegistry rg = RepositoryRegistry.vmtMANAGER;
      Set<VMTRootObject> vObjList = rg.getInstances(getSEType());

      if (hourChanged) {
        hourlyTimeStamp =
            (System.currentTimeMillis()
                - (1000 * 60 * 30)); // Give the record TS of the middle of the last hour
      }

      for (VMTRootObject vObj : vObjList) {
        boolean constraintfailed = false;
        // Check constraints
        for (Constraint constraint : getMatchingCriteria()) {
          if (!constraint.match(vObj)) {
            constraintfailed = true;
            break;
          }
        }

        // and skip if any of the constraints do not match
        if (constraintfailed) {
          continue;
        }

        ServiceEntity se = (ServiceEntity) vObj;
        if (DeployManager.vmtMANAGER.inDeploy(se)) {
          continue;
        }

        // Get the Extension for ServiceEntity
        ServiceEntityReportingExt seExt =
            (ServiceEntityReportingExt)
                se.findExtension(
                    ReportingExtensionsPackage.eINSTANCE.getServiceEntityReportingExt());
        if (seExt == null) {
          seExt = ReportingExtensionsFactory.eINSTANCE.createServiceEntityReportingExt();
          se.getExtendedBy().add(seExt);
        }

        for (NamedElementList neList : getNamedElementList()) {
          if (neList.getNamedElement().size() == 1) {
            EStructuralFeature attribute = (EStructuralFeature) neList.getNamedElement().get(0);
            // Only create a record if the attribute has been set already
            if (vObj.eIsSet(attribute)) {
              Object attributeValue = vObj.eGet(attribute);
              if (attributeValue instanceof List<?>) {
                if (hourChanged) {
                  // Record Object
                  ReportingRecord record =
                      this.createReportingRecord(
                          seExt, vObj, attribute, null, null, true, hourlyTimeStamp);
                  if (record != null) {
                    returnList.add(record);
                  }
                  // reset only numProduces fields
                  seExt.resetValues(attribute);
                }
                // this condition for numProduces value
                seExt.setMinNumProduces(((List<?>) attributeValue).size());
                seExt.setMaxNumProduces(((List<?>) attributeValue).size());
                seExt.setProducesSum(((List<?>) attributeValue).size());
                // if(logger.isDebugEnabled())logger.debug("numProduces : min = " +
                // seExt.getMinNumProduces() + " max = " + seExt.getMaxNumProduces() + " sum = " +
                // seExt.getProducesSum());
              } else {
                double val = Double.parseDouble(attributeValue.toString());
                if (val > PRICE_THRESHOLD) {
                  val = PRICE_THRESHOLD;
                }

                if (attribute == AnalysisPackage.eINSTANCE.getServiceEntity_PriceIndex()) {
                  if (val < 0) {
                    if (logger.isDebugEnabled()) {
                      logger.error(
                          "SE : " + vObj.toVMTString() + " has a negative value of " + val);
                      for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
                        logger.debug(element.toString());
                      }
                    }
                    continue;
                  }
                }

                List<EAttribute> atts = seExt.getExtAttributes(attribute);
                for (EAttribute att : atts) {
                  seExt.eSet(att, val);
                }
                if (hourChanged) {
                  // Record Object
                  ReportingRecord record =
                      this.createReportingRecord(
                          seExt, vObj, attribute, null, null, false, hourlyTimeStamp);
                  if (record != null) {
                    returnList.add(record);
                  }
                  // reset only UtilIndex fields
                  seExt.resetValues(attribute);
                }
              }
            }
            // Or get the list of attribute values and create a record for each
          } else {
            EReference reference = (EReference) neList.getNamedElement().get(0);
            ENamedElement commodity = neList.getNamedElement().get(1);
            EStructuralFeature attribute =
                (EStructuralFeature)
                    neList.getNamedElement().get(neList.getNamedElement().size() - 1);

            List<ENamedElement> nesCommodity =
                new ArrayList<ENamedElement>(neList.getNamedElement());
            nesCommodity.remove(neList.getNamedElement().size() - 1);
            List<Object> commodityList = vObj.getValues(nesCommodity);

            for (int i = 0; i < commodityList.size(); i++) {
              Commodity comm = (Commodity) commodityList.get(i);
              // get the attribute value from the commodity if it is set
              if (comm.eIsSet(attribute)) {
                Object attributeValue = comm.eGet(attribute);
                // logger.info("comm att " + comm.getName() + " " + attribute.getName() + " value =
                // " + attributeValue);
                CommodityReportingExt crExt = null;
                for (Extension ext : comm.getExtendedBy()) {
                  if (ext instanceof CommodityReportingExt) {
                    crExt = (CommodityReportingExt) ext;
                    if (crExt.getAttribute() == attribute) {
                      break;
                    } else {
                      crExt = null;
                    }
                  }
                }
                if (crExt == null) {
                  crExt = ReportingExtensionsFactory.eINSTANCE.createCommodityReportingExt();
                  crExt.setAttribute(attribute);
                  comm.getExtendedBy().add(crExt);
                }

                if (hourChanged) {
                  // Record Object
                  ReportingRecord record =
                      this.createReportingRecord(
                          crExt, vObj, attribute, commodity, comm, false, hourlyTimeStamp);
                  if (record != null) {
                    returnList.add(record);
                  }
                  crExt.resetValues();
                }
                // this condition for capacity, used and utilization values
                crExt.setMinUtilization(Double.parseDouble(attributeValue.toString()));
                if (attribute.equals(AnalysisPackage.eINSTANCE.getCommodity_Used())
                    && comm.eIsSet(AnalysisPackage.eINSTANCE.getCommodity_Peak())) {
                  crExt.setMaxUtilization(comm.getPeak());
                } else if (attribute.equals(AnalysisPackage.eINSTANCE.getCommodity_Utilization())
                    && comm.eIsSet(AnalysisPackage.eINSTANCE.getCommodity_PeakUtilization())) {
                  crExt.setMaxUtilization(comm.getPeakUtilization());
                } else {
                  crExt.setMaxUtilization(Double.parseDouble(attributeValue.toString()));
                }
                crExt.setUtilSum(Double.parseDouble(attributeValue.toString()));

                float capacity = comm.getCapacity();
                if (capacity > CAPACITY_THRESHOLD) {
                  if (logger.isDebugEnabled()) {
                    logger.debug(
                        "Capacity for "
                            + se.getDisplayName()
                            + "::"
                            + comm.getDisplayName()
                            + " is "
                            + capacity
                            + ". Capping it to "
                            + CAPACITY_THRESHOLD);
                  }
                  capacity = CAPACITY_THRESHOLD;
                }
                crExt.setCapacity(capacity);
                crExt.setRelation(
                    RelationType.valueOf(reference.getName().toUpperCase()).getValue());
                crExt.setCommodityKey(comm.getKey());
                // if(logger.isDebugEnabled())logger.debug("comm -> " + attribute.getName() + " min
                // = " + crExt.getMinUtilization() + " max = " + crExt.getMaxUtilization() + " sum =
                // " + crExt.getUtilSum() + " cap = " + crExt.getCapacity());
              }
            }
          }
        }
      }
    } catch (Exception e) {
      logger.error("Exception in MetaRecordImpl.getReportingRecordList()", e);
    }
    return returnList;
  }
  /**
   * This method creates a {@link ReportingRecord} object with values from commodity , service
   * entity and attribute provided to it every hour.
   *
   * @param reportingExtension Extension object
   * @param vObj ServiceEntity object
   * @param attribute attribute reported on
   * @param commodityName Commodity named element
   * @param commodity {@link Commodity} object to get provider uuid
   * @param isNumProduces whether reporting on numProduces attribute
   * @return {@link ReportingRecord} object
   */
  private ReportingRecord createReportingRecord(
      ReportingExtension reportingExtension,
      VMTRootObject vObj,
      EStructuralFeature attribute,
      ENamedElement commodityName,
      Commodity commodity,
      boolean isNumProduces,
      long snapshotTime) {
    ReportingRecord record = ReportingFactory.eINSTANCE.createReportingRecord();
    try {
      // long snapshotTime = (System.currentTimeMillis() - (1000*60*60));
      if (reportingExtension.eClass()
          == ReportingExtensionsPackage.eINSTANCE.getCommodityReportingExt()) {
        CommodityReportingExt crExt = (CommodityReportingExt) reportingExtension;
        if (crExt.getMinUtilization() == -1d || crExt.getMaxUtilization() == -1d) {
          return null;
        }
        record.setTimeStamp(snapshotTime);
        record.setSeUuId(vObj.getUuid());
        record.setPropertyType(commodityName.getName());
        record.setPropertySubType(attribute.getName());
        record.setMinUtilization(crExt.getMinUtilization());
        record.setMaxUtilization(crExt.getMaxUtilization());
        record.setAvgUtilization(crExt.getAvgUtilization());
        record.setCapacity(crExt.getCapacity());
        record.setRelation(crExt.getRelation());

        if (crExt.getCommodityKey() != null) {
          String commodityKey = truncateString(crExt.getCommodityKey(), 80);
          record.setCommodityKey(commodityKey);
        }

        if (!commodity.getConsumes().isEmpty()
            && commodity.getConsumes().get(0).getSoldBy() != null) {
          record.setProviderUuId(commodity.getConsumes().get(0).getSoldBy().getUuid());
        }
        // record.setStdDev(0);
      } else if (reportingExtension.eClass()
          == ReportingExtensionsPackage.eINSTANCE.getServiceEntityReportingExt()) {
        ServiceEntityReportingExt seExt = (ServiceEntityReportingExt) reportingExtension;
        if (isNumProduces) {
          if (seExt.getMinNumProduces() == -1 || seExt.getMaxNumProduces() == -1) {
            return null;
          }
          record.setTimeStamp(snapshotTime);
          record.setSeUuId(vObj.getUuid());
          record.setPropertyType(attribute.getName());
          record.setPropertySubType(attribute.getName());
          record.setMinUtilization(seExt.getMinNumProduces());
          record.setMaxUtilization(seExt.getMaxNumProduces());
          record.setAvgUtilization(seExt.getAvgProduces());
          record.setRelation(-1);
          record.setCommodityKey(null);
          // record.setStdDev(0);
        } else {

          if (seExt.getMinPropValue() == -1d || seExt.getMaxPropValue() == -1d) {
            return null;
          }

          if (attribute == AnalysisPackage.eINSTANCE.getServiceEntity_PriceIndex()) {
            if ((seExt.getMinPropValue() < 0)
                || (seExt.getMaxPropValue() < 0)
                || (seExt.getAvgPropValue() < 0)) {
              if (logger.isDebugEnabled()) {
                logger.error(
                    "SE : "
                        + vObj.toVMTString()
                        + " has max, min and avg PriceIndex values of "
                        + seExt.getMaxPropValue()
                        + ", "
                        + seExt.getMinPropValue()
                        + " and "
                        + seExt.getAvgPropValue()
                        + " respectively");
              }
              return null;
            }
          }

          record.setTimeStamp(snapshotTime);
          record.setSeUuId(vObj.getUuid());
          record.setPropertyType(attribute.getName());
          record.setPropertySubType(attribute.getName());
          record.setRelation(-1);
          record.setCommodityKey(null);
          record.setMinUtilization(seExt.getMinPropValue());
          record.setMaxUtilization(seExt.getMaxPropValue());
          record.setAvgUtilization(seExt.getAvgPropValue());
        }
      }
    } catch (Exception e) {
      logger.error("Exception in creating record ", e);
    }
    return record;
  }