001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2016, 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 java.util.ArrayList; 033import java.util.List; 034 035import javax.measure.UnitConverter; 036 037/** 038 * <p> 039 * The base class for our {@link UnitConverter} implementations. 040 * </p> 041 * 042 * @author <a href="mailto:units@catmedia.us">Werner Keil</a> 043 * @version 0.8.1, $Date: 2016-01-17 $ 044 */ 045public abstract class AbstractConverter implements UnitConverter { 046 047 /** 048 * 049 */ 050 // private static final long serialVersionUID = 5790242858468427131L; 051 052 /** 053 * The ratio of the circumference of a circle to its diameter. 054 **/ 055 protected static final double PI = 3.1415926535897932384626433832795; 056 057 /** 058 * Holds identity converter. 059 */ 060 public static final AbstractConverter IDENTITY = new Identity(); 061 062 /** 063 * Default constructor. 064 */ 065 protected AbstractConverter() { 066 } 067 068 /** 069 * Concatenates this physics converter with another unit converter. The resulting converter is equivalent to first converting by the specified 070 * converter (right converter), and then converting by this converter (left converter). 071 * 072 * @param that 073 * the other converter. 074 * @return the concatenation of this converter with that converter. 075 */ 076 public AbstractConverter concatenate(AbstractConverter that) { 077 return (that == IDENTITY) ? this : new Pair(this, that); 078 } 079 080 public boolean isIdentity() { 081 return false; 082 } 083 084 @Override 085 public abstract boolean equals(Object cvtr); 086 087 @Override 088 public abstract int hashCode(); 089 090 @Override 091 public abstract AbstractConverter inverse(); 092 093 @Override 094 public UnitConverter concatenate(UnitConverter converter) { 095 return (converter == IDENTITY) ? this : new Pair(this, converter); 096 } 097 098 @Override 099 public List<? extends UnitConverter> getConversionSteps() { 100 final List<AbstractConverter> steps = new ArrayList<AbstractConverter>(); 101 steps.add(this); 102 return steps; 103 } 104 105 /** 106 * @throws IllegalArgumentException 107 * if the value is </code>null</code>. 108 */ 109 public Number convert(Number value) { 110 if (value != null) { 111 return convert(value.doubleValue()); 112 } else { 113 throw new IllegalArgumentException("Value cannot be null"); 114 } 115 } 116 117 public abstract double convert(double value); 118 119 /** 120 * This class represents the identity converter (singleton). 121 */ 122 private static final class Identity extends AbstractConverter { 123 124 @Override 125 public boolean isIdentity() { 126 return true; 127 } 128 129 @Override 130 public Identity inverse() { 131 return this; 132 } 133 134 @Override 135 public double convert(double value) { 136 return value; 137 } 138 139 @Override 140 public UnitConverter concatenate(UnitConverter converter) { 141 return converter; 142 } 143 144 @Override 145 public boolean equals(Object cvtr) { 146 return (cvtr instanceof Identity); 147 } 148 149 @Override 150 public int hashCode() { 151 return 0; 152 } 153 154 public boolean isLinear() { 155 return true; 156 } 157 } 158 159 /** 160 * This class represents converters made up of two or more separate converters (in matrix notation <code>[pair] = [left] x [right]</code>). 161 */ 162 public static final class Pair extends AbstractConverter { 163 164 /** 165 * Holds the first converter. 166 */ 167 private final UnitConverter left; 168 169 /** 170 * Holds the second converter. 171 */ 172 private final UnitConverter right; 173 174 /** 175 * Creates a compound converter resulting from the combined transformation of the specified converters. 176 * 177 * @param left 178 * the left converter. 179 * @param right 180 * the right converter. 181 * @throws IllegalArgumentException 182 * if either the left or right converter are </code>null</code> 183 */ 184 public Pair(UnitConverter left, UnitConverter right) { 185 this.left = left; 186 this.right = right; 187 } 188 189 public boolean isLinear() { 190 return left.isLinear() && right.isLinear(); 191 } 192 193 @Override 194 public boolean isIdentity() { 195 return false; 196 } 197 198 @Override 199 public List<UnitConverter> getConversionSteps() { 200 final List<UnitConverter> steps = new ArrayList<UnitConverter>(); 201 List<? extends UnitConverter> leftCompound = left.getConversionSteps(); 202 List<? extends UnitConverter> rightCompound = right.getConversionSteps(); 203 steps.addAll(leftCompound); 204 steps.addAll(rightCompound); 205 return steps; 206 } 207 208 @Override 209 public Pair inverse() { 210 return new Pair(right.inverse(), left.inverse()); 211 } 212 213 @Override 214 public double convert(double value) { 215 return left.convert(right.convert(value)); 216 } 217 218 @Override 219 public boolean equals(Object cvtr) { 220 if (this == cvtr) 221 return true; 222 if (!(cvtr instanceof Pair)) 223 return false; 224 Pair that = (Pair) cvtr; 225 return (this.left.equals(that.left)) && (this.right.equals(that.right)); 226 } 227 228 @Override 229 public int hashCode() { 230 return left.hashCode() + right.hashCode(); 231 } 232 233 public UnitConverter getLeft() { 234 return left; 235 } 236 237 public UnitConverter getRight() { 238 return right; 239 } 240 } 241}