001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2018, Jean-Marie Dautelle, Werner Keil, Otavio Santana. 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-385, Indriya nor the names of their 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 tech.units.indriya; 031 032import javax.measure.Dimension; 033import javax.measure.Quantity; 034import javax.measure.Unit; 035import javax.measure.spi.SystemOfUnits; 036 037import tech.units.indriya.format.SimpleUnitFormat; 038import tech.units.indriya.format.UnitStyle; 039import tech.uom.lib.common.function.Nameable; 040 041import static tech.units.indriya.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.1, April 1, 2018 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 * 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 @Override 087 public Set<Unit<?>> getUnits() { 088 return Collections.unmodifiableSet(units); 089 } 090 091 @Override 092 public Set<? extends Unit<?>> getUnits(Dimension dimension) { 093 return this.getUnits().stream().filter(unit -> dimension.equals(unit.getDimension())) 094 .collect(Collectors.toSet()); 095 } 096 097 @SuppressWarnings("unchecked") 098 @Override 099 public <Q extends Quantity<Q>> Unit<Q> getUnit(Class<Q> quantityType) { 100 return quantityToUnit.get(quantityType); 101 } 102 103 protected static class Helper { 104 static Set<Unit<?>> getUnitsOfDimension(final Set<Unit<?>> units, Dimension dimension) { 105 if (dimension != null) { 106 return units.stream().filter(u -> dimension.equals(u.getDimension())).collect(Collectors.toSet()); 107 108 } 109 return null; 110 } 111 112 /** 113 * Adds a new named unit to the collection. 114 * 115 * @param unit 116 * the unit being added. 117 * @param name 118 * the name of the unit. 119 * @return <code>unit</code>. 120 * @since 1.0 121 */ 122 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String name) { 123 return addUnit(units, unit, name, NAME); 124 } 125 126 /** 127 * Adds a new named unit to the collection. 128 * 129 * @param unit 130 * the unit being added. 131 * @param name 132 * the name of the unit. 133 * @param name 134 * the symbol of the unit. 135 * @return <code>unit</code>. 136 * @since 1.0 137 */ 138 @SuppressWarnings("unchecked") 139 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String name, String symbol) { 140 if (name != null && symbol != null && unit instanceof AbstractUnit) { 141 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 142 aUnit.setName(name); 143 aUnit.setSymbol(symbol); 144 units.add(aUnit); 145 return (U) aUnit; 146 } 147 if (name != null && unit instanceof AbstractUnit) { 148 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 149 aUnit.setName(name); 150 units.add(aUnit); 151 return (U) aUnit; 152 } 153 units.add(unit); 154 return unit; 155 } 156 157 /** 158 * Adds a new named unit to the collection. 159 * 160 * @param unit 161 * the unit being added. 162 * @param name 163 * the name of the unit. 164 * @param name 165 * the symbol of the unit. 166 * @param style 167 * style of the unit. 168 * @return <code>unit</code>. 169 * @since 1.0.1 170 */ 171 @SuppressWarnings("unchecked") 172 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, final String name, final String symbol, UnitStyle style) { 173 switch (style) { 174 case NAME: 175 case SYMBOL: 176 case SYMBOL_AND_LABEL: 177 if (name != null && symbol != null && unit instanceof AbstractUnit) { 178 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 179 aUnit.setName(name); 180 if (SYMBOL.equals(style) || SYMBOL_AND_LABEL.equals(style)) { 181 aUnit.setSymbol(symbol); 182 } 183 if (LABEL.equals(style) || SYMBOL_AND_LABEL.equals(style)) { 184 SimpleUnitFormat.getInstance().label(unit, symbol); 185 } 186 units.add(aUnit); 187 return (U) aUnit; 188 } 189 if (name != null && unit instanceof AbstractUnit) { 190 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 191 aUnit.setName(name); 192 units.add(aUnit); 193 return (U) aUnit; 194 } 195 break; 196 default: 197 if (logger.isLoggable(Level.FINEST)) { 198 logger.log(Level.FINEST, "Unknown style " + style + "; unit " + unit + " can't be rendered with '" + symbol + "'."); 199 } 200 break; 201 } 202 if (LABEL.equals(style) || SYMBOL_AND_LABEL.equals(style)) { 203 SimpleUnitFormat.getInstance().label(unit, symbol); 204 } 205 units.add(unit); 206 return unit; 207 } 208 209 /** 210 * Adds a new labeled unit to the set. 211 * 212 * @param units 213 * the set to add to. 214 * 215 * @param unit 216 * the unit being added. 217 * @param text 218 * the text for the unit. 219 * @param style 220 * style of the unit. 221 * @return <code>unit</code>. 222 * @since 1.0.1 223 */ 224 @SuppressWarnings("unchecked") 225 public static <U extends Unit<?>> U addUnit(Set<Unit<?>> units, U unit, String text, UnitStyle style) { 226 switch (style) { 227 case NAME: 228 if (text != null && unit instanceof AbstractUnit) { 229 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 230 aUnit.setName(text); 231 units.add(aUnit); 232 return (U) aUnit; 233 } 234 break; 235 case SYMBOL: 236 if (text != null && unit instanceof AbstractUnit) { 237 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 238 aUnit.setSymbol(text); 239 units.add(aUnit); 240 return (U) aUnit; 241 } 242 break; 243 case SYMBOL_AND_LABEL: 244 if (text != null && unit instanceof AbstractUnit) { 245 AbstractUnit<?> aUnit = (AbstractUnit<?>) unit; 246 aUnit.setSymbol(text); 247 units.add(aUnit); 248 SimpleUnitFormat.getInstance().label(aUnit, text); 249 return (U) aUnit; 250 } else { // label in any case, returning below 251 SimpleUnitFormat.getInstance().label(unit, text); 252 } 253 break; 254 case LABEL: 255 SimpleUnitFormat.getInstance().label(unit, text); 256 break; 257 default: 258 logger.log(Level.FINEST, "Unknown style " + style + "; unit " + unit + " can't be rendered with '" + text + "'."); 259 break; 260 } 261 units.add(unit); 262 return unit; 263 } 264 } 265}