001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2017, Jean-Marie Dautelle, Werner Keil, V2COM. 004 * 005 * All rights reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without modification, 008 * are permitted provided that the following conditions are met: 009 * 010 * 1. Redistributions of source code must retain the above copyright notice, 011 * this list of conditions and the following disclaimer. 012 * 013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 014 * and the following disclaimer in the documentation and/or other materials provided with the distribution. 015 * 016 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products 017 * derived from this software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package tec.units.ri; 031 032import static tec.units.ri.format.UnitStyle.*; 033 034import java.util.HashMap; 035import java.util.HashSet; 036import java.util.Map; 037import java.util.Set; 038import java.util.logging.Level; 039import java.util.logging.Logger; 040 041import javax.measure.Dimension; 042import javax.measure.Quantity; 043import javax.measure.Unit; 044import javax.measure.spi.SystemOfUnits; 045 046import tec.units.ri.format.SimpleUnitFormat; 047import tec.units.ri.format.UnitStyle; 048 049/** 050 * <p> 051 * An abstract base class for unit systems. 052 * </p> 053 * 054 * @author <a href="mailto:units@catmedia.us">Werner Keil</a> 055 * @version 1.0.4, October 7, 2016 056 */ 057public abstract class AbstractSystemOfUnits implements SystemOfUnits { 058 protected static final Logger logger = Logger.getLogger(AbstractSystemOfUnits.class.getName()); 059 060 /** 061 * Holds the units. 062 */ 063 protected final Set<Unit<?>> units = new HashSet<Unit<?>>(); 064 065 /** 066 * Holds the mapping quantity to unit. 067 */ 068 @SuppressWarnings("rawtypes") 069 protected final Map<Class<? extends Quantity>, Unit> quantityToUnit = new HashMap<Class<? extends Quantity>, Unit>(); 070 071 /** 072 * The natural logarithm. 073 */ 074 protected static final double E = 2.71828182845904523536028747135266; 075 076 /* 077 * (non-Javadoc) 078 * 079 * @see SystemOfUnits#getName() 080 */ 081 public abstract String getName(); 082 083 // /////////////////// 084 // Collection View // 085 // /////////////////// 086 public Set<Unit<?>> getUnits() { 087 if (logger.isLoggable(Level.FINEST)) { 088 for (Unit<?> u : units) { 089 logger.log(Level.FINEST, u + "; D: " + u.getDimension() + "; C: " + u.getClass()); 090 } 091 } 092 return units; 093 } 094 095 @Override 096 public Set<? extends Unit<?>> getUnits(Dimension dimension) { 097 final Set<Unit<?>> set = new HashSet<Unit<?>>(); 098 for (Unit<?> unit : this.getUnits()) { 099 if (dimension.equals(unit.getDimension())) { 100 set.add(unit); 101 } 102 } 103 return set; 104 } 105 106 @SuppressWarnings("unchecked") 107 public <Q extends Quantity<Q>> Unit<Q> getUnit(Class<Q> quantityType) { 108 return quantityToUnit.get(quantityType); 109 } 110 111 protected static final class Helper { 112 static Set<Unit<?>> getUnitsOfDimension(final Set<Unit<?>> units, Dimension dimension) { 113 if (dimension != null) { 114 Set<Unit<?>> dimSet = new HashSet<Unit<?>>(); 115 for (Unit<?> u : units) { 116 if (dimension.equals(u.getDimension())) { 117 dimSet.add(u); 118 } 119 } 120 return dimSet; 121 } 122 return null; 123 } 124 125 /** 126 * Adds a new named unit to the collection. 127 * 128 * @param unit 129 * the unit being added. 130 * @param name 131 * the name of the unit. 132 * @return <code>unit</code>. 133 * @since 1.0 134 */ 135 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String name) { 136 return addUnit(units, unit, name, NAME); 137 } 138 139 /** 140 * Adds a new named unit to the collection. 141 * 142 * @param unit 143 * the unit being added. 144 * @param name 145 * the name of the unit. 146 * @param name 147 * the symbol of the unit. 148 * @param style 149 * style of the unit. 150 * @return <code>unit</code>. 151 * @since 1.0.1 152 */ 153 @SuppressWarnings("unchecked") 154 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, final String name, final String symbol, UnitStyle style) { 155 switch (style) { 156 case NAME: 157 case SYMBOL: 158 case SYMBOL_AND_LABEL: 159 if (name != null && symbol != null && unit instanceof AbstractUnit) { 160 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 161 aUnit.setName(name); 162 if (SYMBOL.equals(style) || SYMBOL_AND_LABEL.equals(style)) { 163 aUnit.setSymbol(symbol); 164 } 165 if (LABEL.equals(style) || SYMBOL_AND_LABEL.equals(style)) { 166 SimpleUnitFormat.getInstance().label(unit, symbol); 167 } 168 units.add(aUnit); 169 return (U) aUnit; 170 } 171 if (name != null && unit instanceof AbstractUnit) { 172 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 173 aUnit.setName(name); 174 units.add(aUnit); 175 return (U) aUnit; 176 } 177 break; 178 default: 179 if (logger.isLoggable(Level.FINEST)) { 180 logger.log(Level.FINEST, "Unknown style " + style + "; unit " + unit + " can't be rendered with '" + symbol + "'."); 181 } 182 break; 183 } 184 if (LABEL.equals(style) || SYMBOL_AND_LABEL.equals(style)) { 185 SimpleUnitFormat.getInstance().label(unit, symbol); 186 } 187 units.add(unit); 188 return unit; 189 } 190 191 /** 192 * Adds a new labeled unit to the set. 193 * 194 * @param units 195 * the set to add to. 196 * 197 * @param unit 198 * the unit being added. 199 * @param text 200 * the text for the unit. 201 * @param style 202 * style of the unit. 203 * @return <code>unit</code>. 204 * @since 1.0.1 205 */ 206 @SuppressWarnings("unchecked") 207 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String text, UnitStyle style) { 208 switch (style) { 209 case NAME: 210 if (text != null && unit instanceof AbstractUnit) { 211 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 212 aUnit.setName(text); 213 units.add(aUnit); 214 return (U) aUnit; 215 } 216 break; 217 case SYMBOL: 218 if (text != null && unit instanceof AbstractUnit) { 219 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 220 aUnit.setSymbol(text); 221 units.add(aUnit); 222 return (U) aUnit; 223 } 224 break; 225 case SYMBOL_AND_LABEL: 226 if (text != null && unit instanceof AbstractUnit) { 227 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 228 aUnit.setSymbol(text); 229 units.add(aUnit); 230 SimpleUnitFormat.getInstance().label(aUnit, text); 231 return (U) aUnit; 232 } else { // label in any case, returning below 233 SimpleUnitFormat.getInstance().label(unit, text); 234 } 235 break; 236 case LABEL: 237 SimpleUnitFormat.getInstance().label(unit, text); 238 break; 239 default: 240 logger.log(Level.FINEST, "Unknown style " + style + "; unit " + unit + " can't be rendered with '" + text + "'."); 241 break; 242 } 243 units.add(unit); 244 return unit; 245 } 246 247 /** 248 * Adds a new named unit to the collection. 249 * 250 * @param unit 251 * the unit being added. 252 * @param name 253 * the name of the unit. 254 * @param name 255 * the symbol of the unit. 256 * @return <code>unit</code>. 257 * @since 1.0 258 */ 259 @SuppressWarnings("unchecked") 260 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, final String name, final String symbol) { 261 if (name != null && symbol != null && unit instanceof AbstractUnit) { 262 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 263 aUnit.setName(name); 264 aUnit.setSymbol(symbol); 265 units.add(aUnit); 266 return (U) aUnit; 267 } 268 if (name != null && unit instanceof AbstractUnit) { 269 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 270 aUnit.setName(name); 271 units.add(aUnit); 272 return (U) aUnit; 273 } 274 if (symbol != null && unit instanceof AbstractUnit) { 275 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 276 aUnit.setSymbol(symbol); 277 units.add(aUnit); 278 return (U) aUnit; 279 } 280 units.add(unit); 281 return unit; 282 } 283 } 284}