content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.ambari.server.controller.metrics.ganglia;
  
  import java.util.Collections;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  
  /**
   * Data structure for temporal data returned from Ganglia Web.
   */
  @JsonIgnoreProperties(ignoreUnknown = true)
  public class GangliaMetric {
  
    // Note that the member names correspond to the names in the JSON returned from Ganglia Web.
  
    /**
     * The name.
     */
    private String ds_name;
  
    /**
     * The ganglia cluster name.
     */
    private String cluster_name;
  
    /**
     * The graph type.
     */
    private String graph_type;
  
    /**
     * The host name.
     */
    private String host_name;
  
    /**
     * The metric name.
     */
    private String metric_name;
  
    /**
     * The temporal data points.
     */
    private Number[][] datapoints;
    
    
    private static final Set<String> PERCENTAGE_METRIC;
  
    //BUG-3386 Cluster CPU Chart is off the charts
    // Here can be added other percentage metrics
    static {
      Set<String> temp = new HashSet<>();
      temp.add("cpu_wio");
      temp.add("cpu_idle");
      temp.add("cpu_nice");
      temp.add("cpu_aidle");
      temp.add("cpu_system");
      temp.add("cpu_user");
      PERCENTAGE_METRIC = Collections.unmodifiableSet(temp);
    }
  
  
    // ----- GangliaMetric -----------------------------------------------------
  
    public String getDs_name() {
      return ds_name;
    }
  
    public void setDs_name(String ds_name) {
      this.ds_name = ds_name;
    }
  
    public String getCluster_name() {
      return cluster_name;
    }
  
    public void setCluster_name(String cluster_name) {
      this.cluster_name = cluster_name;
    }
  
    public String getGraph_type() {
      return graph_type;
    }
  
    public void setGraph_type(String graph_type) {
      this.graph_type = graph_type;
    }
  
    public String getHost_name() {
      return host_name;
    }
  
    public void setHost_name(String host_name) {
      this.host_name = host_name;
    }
  
    public String getMetric_name() {
      return metric_name;
    }
  
    public void setMetric_name(String metric_name) {
      this.metric_name = metric_name;
    }
  
    public Number[][] getDatapoints() {
      return datapoints;
    }
  
  
    public void setDatapoints(Number[][] datapoints) {
      this.datapoints = datapoints;
    } 
    
    public void setDatapointsFromList(List<GangliaMetric.TemporalMetric> listTemporalMetrics) { 
      //this.datapoints = datapoints;
      Number[][] datapointsArray = new Number[listTemporalMetrics.size()][2];
      int cnt = 0;
      if (PERCENTAGE_METRIC.contains(metric_name)) {
        int firstIndex = 0;
        int lastIndex = listTemporalMetrics.size() - 1;
        for (int i = firstIndex; i <= lastIndex; ++i) {
          GangliaMetric.TemporalMetric m = listTemporalMetrics.get(i);
          Number val = m.getValue();
          if (100.0 >= val.doubleValue()) {
            datapointsArray[cnt][0] = val;
            datapointsArray[cnt][1] = m.getTime();
            cnt++;
          }
        }
      } else {
        int firstIndex = 0;
        int lastIndex = listTemporalMetrics.size() - 1;
        for (int i = firstIndex; i <= lastIndex; ++i) {
          GangliaMetric.TemporalMetric m = listTemporalMetrics.get(i);
          datapointsArray[i][0] = m.getValue();
          datapointsArray[i][1] = m.getTime();
          cnt++;
        }
      }
  
      this.datapoints = new Number[cnt][2];
      for (int i = 0; i < this.datapoints.length; i++) {
        this.datapoints[i][0] = datapointsArray[i][0];
        this.datapoints[i][1] = datapointsArray[i][1];
      }
  
    }
  
    // ----- Object overrides --------------------------------------------------
  
    @Override
    public String toString() {
      StringBuilder stringBuilder = new StringBuilder();
  
      stringBuilder.append("\n");
      stringBuilder.append("name=");
      stringBuilder.append(ds_name);
      stringBuilder.append("\n");
      stringBuilder.append("cluster name=");
      stringBuilder.append(cluster_name);
      stringBuilder.append("\n");
      stringBuilder.append("graph type=");
      stringBuilder.append(graph_type);
      stringBuilder.append("\n");
      stringBuilder.append("host name=");
      stringBuilder.append(host_name);
      stringBuilder.append("\n");
      stringBuilder.append("api name=");
      stringBuilder.append(metric_name);
      stringBuilder.append("\n");
  
      stringBuilder.append("datapoints (value/timestamp):");
      stringBuilder.append("\n");
  
  
      boolean first = true;
      stringBuilder.append("[");
      for (Number[] m : datapoints) {
        if (!first) {
          stringBuilder.append(",");
        }
        stringBuilder.append("[");
        stringBuilder.append(m[0]);
        stringBuilder.append(",");
        stringBuilder.append(m[1].longValue());
        stringBuilder.append("]");
        first = false;
      }
      stringBuilder.append("]");
  
      return stringBuilder.toString();
    }
  
    public static class TemporalMetric {
      private Number m_value;
      private Number m_time;
      private boolean valid;
  
      public boolean isValid() {
        return valid;
      }
  
      public TemporalMetric(String value, Number time) {
        valid = true;
        try{
          m_value = convertToNumber(value);
        } catch (NumberFormatException e) {
          valid = false;
        }
        m_time = time;
      }
  
      public Number getValue() {
        return m_value;
      }
  
      public Number getTime() {
        return m_time;
      }
      
      private Number convertToNumber(String s) throws NumberFormatException {
        Number res;
        if(s.contains(".")){
          Double d = Double.parseDouble(s);
          if(d.isNaN() || d.isInfinite()){
            throw new NumberFormatException(s);
          } else {
            res = d;
          } 
        } else {
          res = Long.parseLong(s);
        }
        return res;
      }
      
    }
  }
  