1 /*
2 * Copyright (C) 2018 Alberto Irurueta Carro (alberto@irurueta.com)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.irurueta.units;
17
18 import java.text.ParseException;
19 import java.util.Locale;
20
21 /**
22 * Formats and parses frequency value and unit.
23 */
24 public class FrequencyFormatter extends MeasureFormatter<Frequency, FrequencyUnit> {
25
26 /**
27 * Hertz symbol.
28 */
29 public static final String HERTZ = "Hz";
30
31 /**
32 * KiloHertz symbol.
33 */
34 public static final String KILOHERTZ = "KHz";
35
36 /**
37 * MegaHertz symbol.
38 */
39 public static final String MEGAHERTZ = "MHz";
40
41 /**
42 * GigaHertz symbol.
43 */
44 public static final String GIGAHERTZ = "GHz";
45
46 /**
47 * TeraHertz symbol.
48 */
49 public static final String TERAHERTZ = "THz";
50
51 /**
52 * Constructor.
53 */
54 public FrequencyFormatter() {
55 super();
56 }
57
58 /**
59 * Constructor with locale.
60 *
61 * @param locale locale.
62 * @throws IllegalArgumentException if locale is null.
63 */
64 public FrequencyFormatter(final Locale locale) {
65 super(locale);
66 }
67
68 /**
69 * Copy constructor.
70 *
71 * @param formatter input instance to copy from.
72 * @throws NullPointerException if provided formatter is null.
73 */
74 public FrequencyFormatter(final FrequencyFormatter formatter) {
75 this(formatter.getLocale());
76 }
77
78 /**
79 * Determines if two frequency formatters are equal by comparing all of their
80 * internal parameters.
81 *
82 * @param obj another object to compare.
83 * @return true if provided object is assumed to be equal to this instance.
84 */
85 @Override
86 public boolean equals(final Object obj) {
87 final var equals = super.equals(obj);
88 return (obj instanceof FrequencyFormatter) && equals;
89 }
90
91 /**
92 * Hash code generated for this instance.
93 * Hash codes can be internally used by some collections to coarsely compare objects.
94 * This implementation only calls parent implementation to avoid static analyzer warning.
95 *
96 * @return hash code.
97 */
98 @Override
99 public int hashCode() {
100 return super.hashCode();
101 }
102
103 /**
104 * Gets unit system for detected unit into provided string representation
105 * of a measurement.
106 *
107 * @param source a measurement string representation to be checked.
108 * @return a unit system (either metric or imperial) or null if unit
109 * cannot be determined.
110 */
111 @Override
112 public UnitSystem getUnitSystem(final String source) {
113 return UnitSystem.METRIC;
114 }
115
116 /**
117 * Parses provided string and tries to determine a frequency value and unit.
118 *
119 * @param source a string to be parsed.
120 * @return a frequency containing a value and unit.
121 * @throws ParseException if provided string cannot be parsed.
122 * @throws UnknownUnitException if unit cannot be determined.
123 */
124 @Override
125 public Frequency parse(final String source) throws ParseException, UnknownUnitException {
126 return internalParse(source, new Frequency());
127 }
128
129 /**
130 * Attempts to determine a frequency unit within a frequency string
131 * representation.
132 *
133 * @param source a frequency measurement string representation.
134 * @return a frequency unit, or null if none can be determined.
135 */
136 @Override
137 public FrequencyUnit findUnit(final String source) {
138 if (source.contains(KILOHERTZ + " ") || source.endsWith(KILOHERTZ)) {
139 return FrequencyUnit.KILOHERTZ;
140 }
141 if (source.contains(MEGAHERTZ + " ") || source.endsWith(MEGAHERTZ)) {
142 return FrequencyUnit.MEGAHERTZ;
143 }
144 if (source.contains(GIGAHERTZ + " ") || source.endsWith(GIGAHERTZ)) {
145 return FrequencyUnit.GIGAHERTZ;
146 }
147 if (source.contains(TERAHERTZ + " ") || source.endsWith(TERAHERTZ)) {
148 return FrequencyUnit.TERAHERTZ;
149 }
150 if (source.contains(HERTZ + " ") || source.endsWith(HERTZ)) {
151 return FrequencyUnit.HERTZ;
152 }
153 return null;
154 }
155
156 /**
157 * Formats and converts provided frequency value and unit using provided unit
158 * system.
159 * If provided value is too large for provided unit, this method will convert
160 * it to a more appropriate unit. This implementation ignores unit system.
161 *
162 * @param value a measurement value.
163 * @param unit a measurement unit.
164 * @param system system unit to convert measurement to (it is ignored).
165 * @return a string representation of frequency value and unit.
166 */
167 @Override
168 public String formatAndConvert(final Number value, final FrequencyUnit unit, final UnitSystem system) {
169 return formatAndConvertMetric(value, unit);
170 }
171
172 /**
173 * Formats and converts provided frequency value and unit using metric unit
174 * system.
175 * If provided frequency value is too large for provided frequency unit, this
176 * method will convert it to a more appropriate unit.
177 *
178 * @param value a frequency value.
179 * @param unit a frequency unit.
180 * @return a string representation of frequency value and unit using metric
181 * unit system.
182 */
183 public String formatAndConvertMetric(final Number value, final FrequencyUnit unit) {
184 final var v = value.doubleValue();
185
186 final var hertz = FrequencyConverter.convert(v, unit, FrequencyUnit.HERTZ);
187 if (Math.abs(hertz) < FrequencyConverter.HERTZS_PER_KILOHERTZ) {
188 return format(hertz, FrequencyUnit.HERTZ);
189 }
190
191 final var kiloHertz = FrequencyConverter.convert(v, unit, FrequencyUnit.KILOHERTZ);
192 if (Math.abs(kiloHertz) < (FrequencyConverter.HERTZ_PER_MEGAHERTZ / FrequencyConverter.HERTZS_PER_KILOHERTZ)) {
193 return format(kiloHertz, FrequencyUnit.KILOHERTZ);
194 }
195
196 final var megaHertz = FrequencyConverter.convert(v, unit, FrequencyUnit.MEGAHERTZ);
197 if (Math.abs(megaHertz) < (FrequencyConverter.HERTZ_PER_GIGAHERTZ / FrequencyConverter.HERTZ_PER_MEGAHERTZ)) {
198 return format(megaHertz, FrequencyUnit.MEGAHERTZ);
199 }
200
201 final var gigaHertz = FrequencyConverter.convert(v, unit, FrequencyUnit.GIGAHERTZ);
202 if (Math.abs(gigaHertz) < (FrequencyConverter.HERTZ_PER_TERAHERTZ / FrequencyConverter.HERTZ_PER_GIGAHERTZ)) {
203 return format(gigaHertz, FrequencyUnit.GIGAHERTZ);
204 }
205
206 final var teraHertz = FrequencyConverter.convert(v, unit, FrequencyUnit.TERAHERTZ);
207 return format(teraHertz, FrequencyUnit.TERAHERTZ);
208 }
209
210 /**
211 * Returns unit string representation.
212 *
213 * @param unit a frequency unit.
214 * @return its string representation
215 */
216 @SuppressWarnings("DuplicatedCode")
217 @Override
218 public String getUnitSymbol(final FrequencyUnit unit) {
219 return switch (unit) {
220 case KILOHERTZ -> KILOHERTZ;
221 case MEGAHERTZ -> MEGAHERTZ;
222 case GIGAHERTZ -> GIGAHERTZ;
223 case TERAHERTZ -> TERAHERTZ;
224 default -> HERTZ;
225 };
226 }
227
228 /**
229 * Returns unit system this instance will use based on its assigned locale.
230 * Notice that if no locale was assigned, then the default system locale
231 * will be used.
232 *
233 * @return unit system this instance will use.
234 */
235 @Override
236 public UnitSystem getUnitSystem() {
237 return UnitSystem.METRIC;
238 }
239 }