001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.monitoring.counters; 019 020 import java.util.ArrayList; 021 import java.util.Collections; 022 import java.util.List; 023 import java.util.Map; 024 import java.util.Set; 025 import java.util.concurrent.ConcurrentHashMap; 026 import java.util.concurrent.CopyOnWriteArraySet; 027 028 /** 029 * Units allow monitored data to have get typed. A primary unit is the 030 * finest unit for a data type. A primary unit can have derived units, 031 * that represent the same data type, but with a scale factor. 032 * A primary Unit is created with the {@link Unit#Unit(String)} constructor. 033 * A derived Unit is created with the {@link Unit#Unit(String, Unit, long)} constructor. 034 * <p/> 035 * A primary Unit maintains a Map of it's derived units. {@see Unit#getDerived()} can be 036 * used to retrieve the complete list, and {@see Unit#getDerived(String)} to retrieve a 037 * derived unit by it's name. 038 * 039 * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a> 040 */ 041 public class Unit implements Comparable<Unit> { 042 private static final Map<String, Unit> UNITS = new ConcurrentHashMap<String, Unit>(); 043 044 /** 045 * Time based units 046 */ 047 public static class Time extends Unit { 048 public static final Unit NANOSECOND = new Unit("ns"); 049 public static final Unit MICROSECOND = new Unit("µs", NANOSECOND, 1000); 050 public static final Unit MILLISECOND = new Unit("ms", MICROSECOND, 1000); 051 public static final Unit SECOND = new Unit("s", MILLISECOND, 1000); 052 public static final Unit MINUTE = new Unit("min", SECOND, 60); 053 public static final Unit HOUR = new Unit("h", MINUTE, 60); 054 public static final Unit DAY = new Unit("day", HOUR, 24); 055 056 public Time(String name) { 057 super(name); 058 } 059 060 public Time(String name, Unit derived, long scale) { 061 super(name, derived, scale); 062 } 063 064 } 065 066 /** 067 * Binary data units 068 */ 069 public static class Binary 070 extends Unit { 071 072 public static final Unit BYTE = new Unit("b"); 073 074 public static final Unit KBYTE = new Unit("Kb", BYTE, 1024); 075 076 public static final Unit MBYTE = new Unit("Mb", KBYTE, 1024); 077 078 public static final Unit GBYTE = new Unit("Gb", MBYTE, 1024); 079 080 public Binary(String name) { 081 super(name); 082 } 083 084 public Binary(String name, Unit derived, long scale) { 085 super(name, derived, scale); 086 } 087 088 089 } 090 091 /** 092 * unit for basic item counters & gauges 093 */ 094 // "BILLION" does not have same signification depending on country (10^12 or 10^9). 095 // We use International system of unit names to avoid confusion 096 // @see http://en.wikipedia.org/wiki/SI 097 public static final Unit UNARY = new Unit("u"); 098 public static final Unit DECA = new Unit("*10", UNARY, 10); 099 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 }