View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.monitoring.counters;
19  
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Set;
25  import java.util.concurrent.ConcurrentHashMap;
26  import java.util.concurrent.CopyOnWriteArraySet;
27  
28  /**
29   * Units allow monitored data to have get typed. A primary unit is the
30   * finest unit for a data type. A primary unit can have derived units,
31   * that represent the same data type, but with a scale factor.
32   * A primary Unit is created with the {@link Unit#Unit(String)} constructor.
33   * A derived Unit is created with the {@link Unit#Unit(String, Unit, long)} constructor.
34   * <p/>
35   * A primary Unit maintains a Map of it's derived units. {@see Unit#getDerived()} can be
36   * used to retrieve the complete list, and {@see Unit#getDerived(String)} to retrieve a
37   * derived unit by it's name.
38   *
39   * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
40   */
41  public class Unit implements Comparable<Unit> {
42      private static final Map<String, Unit> UNITS = new ConcurrentHashMap<String, Unit>();
43  
44      /**
45       * Time based units
46       */
47      public static class Time extends Unit {
48          public static final Unit NANOSECOND = new Unit("ns");
49          public static final Unit MICROSECOND = new Unit("µs", NANOSECOND, 1000);
50          public static final Unit MILLISECOND = new Unit("ms", MICROSECOND, 1000);
51          public static final Unit SECOND = new Unit("s", MILLISECOND, 1000);
52          public static final Unit MINUTE = new Unit("min", SECOND, 60);
53          public static final Unit HOUR = new Unit("h", MINUTE, 60);
54          public static final Unit DAY = new Unit("day", HOUR, 24);
55  
56          public Time(String name) {
57              super(name);
58          }
59  
60          public Time(String name, Unit derived, long scale) {
61              super(name, derived, scale);
62          }
63  
64      }
65  
66      /**
67       * Binary data units
68       */
69      public static class Binary
70          extends Unit {
71  
72          public static final Unit BYTE = new Unit("b");
73  
74          public static final Unit KBYTE = new Unit("Kb", BYTE, 1024);
75  
76          public static final Unit MBYTE = new Unit("Mb", KBYTE, 1024);
77  
78          public static final Unit GBYTE = new Unit("Gb", MBYTE, 1024);
79  
80          public Binary(String name) {
81              super(name);
82          }
83  
84          public Binary(String name, Unit derived, long scale) {
85              super(name, derived, scale);
86          }
87  
88  
89      }
90  
91      /**
92       * unit for basic item counters & gauges
93       */
94      // "BILLION" does not have same signification depending on country (10^12 or 10^9).
95      // We use International system of unit names to avoid confusion
96      // @see http://en.wikipedia.org/wiki/SI
97      public static final Unit UNARY = new Unit("u");
98      public static final Unit DECA = new Unit("*10", UNARY, 10);
99      public static final Unit HECTO = new Unit("*100", DECA, 10);
100     public static final Unit KILO = new Unit("*1000", HECTO, 10);
101     public static final Unit MEGA = new Unit("*10^6", KILO, 1000);
102     public static final Unit GIGA = new Unit("*10^9", MEGA, 1000);
103     public static final Unit TERA = new Unit("*10^12", GIGA, 1000);
104 
105     private final String name;
106 
107     private final long scale;
108 
109     private Unit primary;
110 
111     private List<Unit> derived;
112 
113     public Set<Unit> primaryUnits = new CopyOnWriteArraySet<Unit>();
114 
115 
116     public static Unit get(String name) {
117         return UNITS.get(name);
118     }
119 
120     /**
121      * Constructor for a primary unit
122      *
123      * @param name
124      */
125     public Unit(String name) {
126         this.name = name;
127         this.primary = this;
128         this.scale = 1;
129         this.derived = new ArrayList<Unit>();
130         this.derived.add(this);
131         primaryUnits.add(this);
132         UNITS.put(name, this);
133     }
134 
135     /**
136      * Constructor for a derived unit
137      *
138      * @param name
139      * @param derived the unit this unit is derived from
140      * @param scale   the scale factor to convert to derived unit
141      */
142     public Unit(String name, Unit derived, long scale) {
143         this.name = name;
144         this.primary = derived.isPrimary() ? derived : derived.getPrimary();
145         this.scale = scale * derived.getScale();
146         primary.derived.add(this);
147         Collections.sort(primary.derived);
148         UNITS.put(name, this);
149     }
150 
151     public Unit getDerived(String name) {
152         for (Unit unit : derived) {
153             if (unit.name.equals(name)) {
154                 return unit;
155             }
156         }
157         return null;
158     }
159 
160     public List<Unit> getDerived() {
161         return Collections.unmodifiableList(derived);
162     }
163 
164 
165     public String getName() {
166         return name;
167     }
168 
169     public long getScale() {
170         return scale;
171     }
172 
173     /**
174      * Convert value from unit to this unit (if conpatible)
175      *
176      * @param value value to convert
177      * @param unit  unit of value
178      * @return value converted to this unit
179      */
180     public double convert(final double value, final Unit unit) {
181         if (unit == this) {
182             return value;
183         }
184         if (!isCompatible(unit)) {
185             throw new IllegalArgumentException("unit " + name + " is incompatible with unit " + unit.name);
186         }
187         return value * unit.getScale() / scale;
188     }
189 
190     public boolean isPrimary() {
191         return primary == this;
192     }
193 
194     public boolean isCompatible(Unit unit) {
195         return primary == unit.getPrimary();
196     }
197 
198     public Unit getPrimary() {
199         return this.primary;
200     }
201 
202     public int compareTo(Unit o) {
203         return scale < o.scale ? -1 : 1;
204     }
205 
206     public String toString() {
207         return name;
208     }
209 
210     /**
211      * @see java.lang.Object#hashCode()
212      */
213     @Override
214     public int hashCode() {
215         final int prime = 31;
216         int result = 1;
217         result = prime * result + ((name == null) ? 0 : name.hashCode());
218         return result;
219     }
220 
221     /**
222      * @see java.lang.Object#equals(java.lang.Object)
223      */
224     @Override
225     public boolean equals(Object obj) {
226         if (this == obj)
227             return true;
228         if (obj == null)
229             return false;
230         if (getClass() != obj.getClass())
231             return false;
232         final Unit other = (Unit) obj;
233         if (name == null) {
234             if (other.name != null)
235                 return false;
236         } else if (!name.equals(other.name))
237             return false;
238         return true;
239     }
240 
241 }