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 com.aliyun.odps.counter;
  
  import java.io.DataInput;
  import java.io.DataOutput;
  import java.io.IOException;
  import java.util.Iterator;
  import java.util.MissingResourceException;
  import java.util.ResourceBundle;
  import java.util.TreeMap;
  
  import com.aliyun.odps.io.Text;
  import com.aliyun.odps.io.Writable;
  import com.aliyun.odps.io.WritableUtils;
  
  /**
   * Counter 组，由多个 {@link Counter} 计数器组成.
   *
   * @see Counter
   * @see Counters
   */
  public class CounterGroup implements Iterable<Counter>, Writable {
  
    private String name;
    private String displayName;
    private TreeMap<String, Counter> counters = new TreeMap<String, Counter>();
    // Optional ResourceBundle for localization of group and counter names.
    private ResourceBundle bundle = null;
  
    /**
     * Returns the specified resource bundle, or throws an exception.
     *
     * @throws MissingResourceException
     *     if the bundle isn't found
     */
    private static ResourceBundle getResourceBundle(String enumClassName) {
      String bundleName = enumClassName.replace('$', '_');
      return ResourceBundle.getBundle(bundleName);
    }
  
    /**
     * CounterGroup构造方法，该方法设置Counter组的名称
     *
     * @param name
     *     Counter组的名称
     */
    protected CounterGroup(String name) {
      this.name = name;
      try {
        bundle = getResourceBundle(name);
      } catch (MissingResourceException neverMind) {
      }
      displayName = localize("CounterGroupName", name);
    }
  
    /**
     * CounterGroup构造方法，该方法设置Counter组的名称和显示名称
     *
     * @param name
     *     Counter组的名称
     * @param displayName
     *     Counter组的显示名称
     */
    protected CounterGroup(String name, String displayName) {
      this.name = name;
      this.displayName = displayName;
    }
  
  
    /**
     * 获取 Counter 组的名称
     *
     * @return Counter 组的名称
     */
    public synchronized String getName() {
      return name;
    }
  
    /**
     * 获取 Counter 组的显示名称
     *
     * @return Counter 组的显示名称
     */
    public synchronized String getDisplayName() {
      return displayName;
    }
  
    /**
     * 增加 {@link Counter} 到此 Counter 组
     *
     * @param counter
     *     待加入的{@link Counter}对象
     */
    synchronized void addCounter(Counter counter) {
      counters.put(counter.getName(), counter);
    }
  
    /**
     * 从 Counter 组查找 {@link Counter}对象，
     * 如果不存在，自动创建 {@link Counter}对象 并加入此 Counter 组.
     *
     * @param counterName
     *     查找的{@link Counter}名称
     * @param displayName
     *     当查找{@link Counter}不存在时，
     *     创建新{@link Counter}指定的显示名称
     * @return 查找到的{@link Counter}对象
     */
    protected Counter findCounter(String counterName, String displayName) {
      Counter result = counters.get(counterName);
      if (result == null) {
        result = new Counter(counterName, displayName);
        counters.put(counterName, result);
      }
      return result;
    }
  
    /**
     * 从 Counter 组查找 {@link Counter}对象，
     * 如果不存在，自动创建 {@link Counter}对象 并加入此 Counter 组.
     *
     * @param counterName
     *     查找的{@link Counter}名称
     * @return 查找到的{@link Counter}对象
     */
    public synchronized Counter findCounter(String counterName) {
      Counter result = counters.get(counterName);
      if (result == null) {
        String displayName = localize(counterName, counterName);
        result = new Counter(counterName, displayName);
        counters.put(counterName, result);
      }
      return result;
    }
  
    /**
     * 返回 Counter的迭代器.
     *
     * @return Counter的迭代器
     */
    public synchronized Iterator<Counter> iterator() {
      return counters.values().iterator();
    }
  
    /**
     * Looks up key in the ResourceBundle and returns the corresponding value. If
     * the bundle or the key doesn't exist, returns the default value.
     */
    private String localize(String key, String defaultValue) {
      String result = defaultValue;
      if (bundle != null) {
        try {
          result = bundle.getString(key);
        } catch (MissingResourceException mre) {
        }
      }
      return result;
    }
  
    /**
     * 返回 Counter 组包含的 Counter 数
     *
     * @return 包含的 Counter 数
     */
    public synchronized int size() {
      return counters.size();
    }
  
    public synchronized boolean equals(Object genericRight) {
      if (genericRight instanceof CounterGroup) {
        Iterator<Counter> right = ((CounterGroup) genericRight).counters.values()
            .iterator();
        Iterator<Counter> left = counters.values().iterator();
        while (left.hasNext()) {
          if (!right.hasNext() || !left.next().equals(right.next())) {
            return false;
          }
        }
        return !right.hasNext();
      }
      return false;
    }
  
    public synchronized int hashCode() {
      return counters.hashCode();
    }
  
    /**
     * 将传入的 Counter 组里的 Counter 值与本 Counter 组的Counter值相加
     *
     * @param rightGroup
     *     待加的 Counter 组
     */
    public synchronized void incrAllCounters(CounterGroup rightGroup) {
      for (Counter right : rightGroup.counters.values()) {
        Counter left = findCounter(right.getName(), right.getDisplayName());
        left.increment(right.getValue());
      }
    }
  
    /**
     * 将本 Counter 组中的 Counter 值置为0
     */
    public synchronized void resetAllCounters() {
      for (Counter counter : this) {
        counter.setValue(0);
      }
    }
  
    /**
     * 将此 Counter 组写到 {@link DataOutput}.
     */
    public synchronized void write(DataOutput out) throws IOException {
      Text.writeString(out, displayName);
      WritableUtils.writeVInt(out, counters.size());
      for (Counter counter : counters.values()) {
        counter.write(out);
      }
    }
  
    /**
     * 从 {@link DataInput} 读取 Counter 组.
     */
    public synchronized void readFields(DataInput in) throws IOException {
      displayName = Text.readString(in);
      counters.clear();
      int size = WritableUtils.readVInt(in);
      for (int i = 0; i < size; i++) {
        Counter counter = new Counter();
        counter.readFields(in);
        counters.put(counter.getName(), counter);
      }
    }
  }
  