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