001/* 002 * Units of Measurement Implementation for Java SE 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.uom.se; 031 032import javax.measure.Dimension; 033import javax.measure.Quantity; 034import javax.measure.Unit; 035import javax.measure.spi.SystemOfUnits; 036 037import tec.uom.lib.common.function.Nameable; 038import tec.uom.se.format.SimpleUnitFormat; 039import tec.uom.se.format.UnitStyle; 040 041import static tec.uom.se.format.UnitStyle.*; 042 043import java.util.*; 044import java.util.logging.Level; 045import java.util.logging.Logger; 046import java.util.stream.Collectors; 047 048/** 049 * <p> 050 * An abstract base class for unit systems. 051 * </p> 052 * 053 * @author <a href="mailto:units@catmedia.us">Werner Keil</a> 054 * @version 1.0.2, November 3, 2016 055 * @since 1.0 056 */ 057public abstract class AbstractSystemOfUnits implements SystemOfUnits, Nameable { 058 /** 059 * Holds the units. 060 */ 061 protected final Set<Unit<?>> units = new HashSet<>(); 062 063 /** 064 * Holds the mapping quantity to unit. 065 */ 066 @SuppressWarnings("rawtypes") 067 protected final Map<Class<? extends Quantity>, Unit> quantityToUnit = new HashMap<>(); 068 069 protected static final Logger logger = Logger.getLogger(AbstractSystemOfUnits.class.getName()); 070 071 /** 072 * Adds a new named unit to the collection. 073 * 074 * @param unit 075 * the unit being added. 076 * @param name 077 * the name of the unit. 078 * @return <code>unit</code>. 079 */ 080 /* 081 * @SuppressWarnings("unchecked") private <U extends Unit<?>> U addUnit(U 082 * unit, String name) { if (name != null && unit instanceof AbstractUnit) { 083 * AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; aUnit.setName(name); 084 * units.add(aUnit); return (U) aUnit; } units.add(unit); return unit; } 085 */ 086 /** 087 * The natural logarithm. 088 **/ 089 protected static final double E = 2.71828182845904523536028747135266; 090 091 /* 092 * (non-Javadoc) 093 * 094 * @see SystemOfUnits#getName() 095 */ 096 public abstract String getName(); 097 098 // /////////////////// 099 // Collection View // 100 // /////////////////// 101 @Override 102 public Set<Unit<?>> getUnits() { 103 return Collections.unmodifiableSet(units); 104 } 105 106 @Override 107 public Set<? extends Unit<?>> getUnits(Dimension dimension) { 108 return this.getUnits().stream().filter(unit -> dimension.equals(unit.getDimension())) 109 .collect(Collectors.toSet()); 110 } 111 112 @SuppressWarnings("unchecked") 113 @Override 114 public <Q extends Quantity<Q>> Unit<Q> getUnit(Class<Q> quantityType) { 115 return quantityToUnit.get(quantityType); 116 } 117 118 protected static class Helper { 119 static Set<Unit<?>> getUnitsOfDimension(final Set<Unit<?>> units, Dimension dimension) { 120 if (dimension != null) { 121 return units.stream().filter(u -> dimension.equals(u.getDimension())).collect(Collectors.toSet()); 122 123 } 124 return null; 125 } 126 127 /** 128 * Adds a new named unit to the collection. 129 * 130 * @param unit 131 * the unit being added. 132 * @param name 133 * the name of the unit. 134 * @return <code>unit</code>. 135 * @since 1.0 136 */ 137 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String name) { 138 return addUnit(units, unit, name, NAME); 139 } 140 141 /** 142 * Adds a new named unit to the collection. 143 * 144 * @param unit 145 * the unit being added. 146 * @param name 147 * the name of the unit. 148 * @param name 149 * the symbol of the unit. 150 * @return <code>unit</code>. 151 * @since 1.0 152 */ 153 @SuppressWarnings("unchecked") 154 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String name, String symbol) { 155 if (name != null && symbol != null && unit instanceof AbstractUnit) { 156 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 157 aUnit.setName(name); 158 aUnit.setSymbol(symbol); 159 units.add(aUnit); 160 return (U) aUnit; 161 } 162 if (name != null && unit instanceof AbstractUnit) { 163 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 164 aUnit.setName(name); 165 units.add(aUnit); 166 return (U) aUnit; 167 } 168 units.add(unit); 169 return unit; 170 } 171 172 /** 173 * Adds a new named unit to the collection. 174 * 175 * @param unit 176 * the unit being added. 177 * @param name 178 * the name of the unit. 179 * @param name 180 * the symbol of the unit. 181 * @param style 182 * style of the unit. 183 * @return <code>unit</code>. 184 * @since 1.0.1 185 */ 186 @SuppressWarnings("unchecked") 187 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, final String name, final String symbol, UnitStyle style) { 188 switch (style) { 189 case NAME: 190 case SYMBOL: 191 case SYMBOL_AND_LABEL: 192 if (name != null && symbol != null && unit instanceof AbstractUnit) { 193 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 194 aUnit.setName(name); 195 if (SYMBOL.equals(style) || SYMBOL_AND_LABEL.equals(style)) { 196 aUnit.setSymbol(symbol); 197 } 198 if (LABEL.equals(style) || SYMBOL_AND_LABEL.equals(style)) { 199 SimpleUnitFormat.getInstance().label(unit, symbol); 200 } 201 units.add(aUnit); 202 return (U) aUnit; 203 } 204 if (name != null && unit instanceof AbstractUnit) { 205 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 206 aUnit.setName(name); 207 units.add(aUnit); 208 return (U) aUnit; 209 } 210 break; 211 default: 212 if (logger.isLoggable(Level.FINEST)) { 213 logger.log(Level.FINEST, "Unknown style " + style + "; unit " + unit + " can't be rendered with '" + symbol + "'."); 214 } 215 break; 216 } 217 if (LABEL.equals(style) || SYMBOL_AND_LABEL.equals(style)) { 218 SimpleUnitFormat.getInstance().label(unit, symbol); 219 } 220 units.add(unit); 221 return unit; 222 } 223 224 /** 225 * Adds a new labeled unit to the set. 226 * 227 * @param units 228 * the set to add to. 229 * 230 * @param unit 231 * the unit being added. 232 * @param text 233 * the text for the unit. 234 * @param style 235 * style of the unit. 236 * @return <code>unit</code>. 237 * @since 1.0.1 238 */ 239 @SuppressWarnings("unchecked") 240 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String text, UnitStyle style) { 241 switch (style) { 242 case NAME: 243 if (text != null && unit instanceof AbstractUnit) { 244 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 245 aUnit.setName(text); 246 units.add(aUnit); 247 return (U) aUnit; 248 } 249 break; 250 case SYMBOL: 251 if (text != null && unit instanceof AbstractUnit) { 252 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 253 aUnit.setSymbol(text); 254 units.add(aUnit); 255 return (U) aUnit; 256 } 257 break; 258 case SYMBOL_AND_LABEL: 259 if (text != null && unit instanceof AbstractUnit) { 260 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 261 aUnit.setSymbol(text); 262 units.add(aUnit); 263 SimpleUnitFormat.getInstance().label(aUnit, text); 264 return (U) aUnit; 265 } else { // label in any case, returning below 266 SimpleUnitFormat.getInstance().label(unit, text); 267 } 268 break; 269 case LABEL: 270 SimpleUnitFormat.getInstance().label(unit, text); 271 break; 272 default: 273 logger.log(Level.FINEST, "Unknown style " + style + "; unit " + unit + " can't be rendered with '" + text + "'."); 274 break; 275 } 276 units.add(unit); 277 return unit; 278 } 279 } 280}