/**
   * Currently the implementation is stupid. It queries for JCatscopia to get All Agents, then it
   * queries for each Agent getAvailableMetrics, and then it asks for all the metrics from each
   * agent. In the future, only metrics that appear in composition rules (filters) should be
   * retrieved, not all in bulk.
   *
   * @return a cluster with monitoring data collected from JCatascopia structured after HostName IP.
   * @throws DataAccessException
   */
  public MonitoringData getMonitoringData() throws DataAccessException {

    MonitoringData monitoringData = new MonitoringData();
    monitoringData.setTimestamp("" + new Date().getTime());
    monitoringData.setSource(url);

    // map for holding the IP, and JCatascopiaAgent, as maybe multiple JCatascopia agents can belong
    // to the same VM, make sure we merge all data
    //        Map<String, JCatascopiaAgent> hostsMap = new HashMap<String, JCatascopiaAgent>();
    //        updateJCatascopiaAgents(poolOfAgents);
    // added to improve query time
    //        if (poolOfAgents.isEmpty()) {
    updateJCatascopiaAgents(poolOfAgents);
    System.err.println("Updating agents");

    for (JCatascopiaAgent agent : poolOfAgents) {
      // if agent is active
      if (agent.getStatus().equalsIgnoreCase("UP")) {
        //                    HostInfo hostInfo = null;
        //                    if (hostsMap.containsKey(agent.getIp())) {
        //                        hostInfo = hostsMap.get(agent.getIp());
        //                    } else {
        //                        hostInfo = new HostInfo();
        //                        hostInfo.setIp(agent.getIp());
        //                        hostInfo.setName(agent.getIp());
        //                        hostsMap.put(hostInfo.getIp(), hostInfo);
        //                    }

        // update metrics using REST API from JCatascopia
        updateMetricsForJCatascopiaAgent(agent);
        getLatestMetricsValuesForJCatascopiaAgent(agent);

        // create monitoring data representation to be returned
        MonitoredElementData elementData = new MonitoredElementData();

        // create representation of monitored element to associate this data in the overall
        // monitored service
        MonitoredElement monitoredElement = new MonitoredElement();

        // for VM level, we use IP as monitored element ID
        monitoredElement.setId(agent.getIp());
        monitoredElement.setName(agent.getId());

        // for the moment we assume all what JCatascopia returns is associated to VM level
        // TODO: consider inserting better level management mechanism in which one data source can
        // return data for multiple levels
        monitoredElement.setLevel(MonitoredElement.MonitoredElementLevel.VM);

        elementData.setMonitoredElement(monitoredElement);

        for (JCatascopiaMetric metric : agent.getAgentMetrics()) {
          if (metric == null || metric.getValue() == null) {
            continue;
          }
          CollectedMetricValue metricInfo = new CollectedMetricValue();
          metricInfo.setName(metric.getName());
          metricInfo.setMonitoredElementLevel(MonitoredElement.MonitoredElementLevel.VM.toString());
          metricInfo.setMonitoredElementID(agent.getIp());
          metricInfo.setType(metric.getType());
          metricInfo.setUnits(metric.getUnit());
          metricInfo.setValue(metric.getValue());
          metricInfo.setTimeSinceCollection("0");
          elementData.addMetric(metricInfo);
        }

        monitoringData.addMonitoredElementData(elementData);

      } else {
        Logger.getLogger(JCatascopiaDataSource.class.getName())
            .log(
                Level.SEVERE,
                "Agent {0} with IP {1} is down",
                new Object[] {agent.getId(), agent.getIp()});
      }
    }
    //        } else {
    //            //added to improve time
    //
    //            for (JCatascopiaAgent agent : poolOfAgents) {
    //                //if agent is active
    //                if (agent.getStatus().equalsIgnoreCase("UP")) {
    ////                    HostInfo hostInfo = null;
    ////                    if (hostsMap.containsKey(agent.getIp())) {
    ////                        hostInfo = hostsMap.get(agent.getIp());
    ////                    } else {
    ////                        hostInfo = new HostInfo();
    ////                        hostInfo.setIp(agent.getIp());
    ////                        hostInfo.setName(agent.getIp());
    ////                        hostsMap.put(hostInfo.getIp(), hostInfo);
    ////                    }
    //
    //                    getLatestMetricsValuesForJCatascopiaAgent(agent);
    //
    //                    //create monitoring data representation to be returned
    //
    //                    MonitoredElementData elementData = new MonitoredElementData();
    //
    //                    //create representation of monitored element to associate this data in the
    // overall monitored service
    //                    MonitoredElement monitoredElement = new MonitoredElement();
    //
    //                    //for VM level, we use IP as monitored element ID
    //                    monitoredElement.setId(agent.getIp());
    //                    monitoredElement.setName(agent.getId());
    //
    //                    //for the moment we assume all what JCatascopia returns is associated to
    // VM level
    //                    //TODO: consider inserting better level management mechanism in which one
    // data source can return data for multiple levels
    //                    monitoredElement.setLevel(MonitoredElement.MonitoredElementLevel.VM);
    //
    //                    elementData.setMonitoredElement(monitoredElement);
    //
    //                    for (JCatascopiaMetric metric : agent.getAgentMetrics()) {
    //                        MetricInfo metricInfo = new MetricInfo();
    //                        metricInfo.setName(metric.getName());
    //                        metricInfo.setType(metric.getType());
    //                        metricInfo.setUnits(metric.getUnit());
    //                        metricInfo.setValue(metric.getValue());
    //                        elementData.addMetric(metricInfo);
    //                    }
    //
    //                    monitoringData.addMonitoredElementData(elementData);
    //
    //                } else {
    //                    Logger.getLogger(JCatascopiaDataSource.class.getName()).log(Level.SEVERE,
    // "Agent {0} with IP {1} is down", new Object[]{agent.getId(), agent.getIp()});
    //                }
    //            }
    //
    //        }

    return monitoringData;
  }