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.format; 031 032import java.io.IOException; 033import java.math.BigDecimal; 034import java.text.ParsePosition; 035import javax.measure.Quantity; 036import javax.measure.Unit; 037import javax.measure.format.MeasurementParseException; 038 039import tech.units.indriya.AbstractQuantity; 040import tech.units.indriya.AbstractUnit; 041import tech.units.indriya.ComparableQuantity; 042import tech.units.indriya.quantity.NumberQuantity; 043import tech.units.indriya.quantity.Quantities; 044 045/** 046 * A simple implementation of QuantityFormat 047 * @version 0.9 048 * @since 2.0 049 */ 050@SuppressWarnings("rawtypes") 051public class SimpleQuantityFormat extends AbstractQuantityFormat { 052 /** 053 * Holds the default format instance. 054 */ 055 private static final SimpleQuantityFormat DEFAULT = new SimpleQuantityFormat(); 056 057 /** 058 * The pattern string of this formatter. This is always a non-localized pattern. 059 * May not be null. See class documentation for details. 060 * 061 * @serial 062 */ 063 private String pattern; 064 065 /** 066 * 067 */ 068 private static final long serialVersionUID = 2758248665095734058L; 069 070 /** 071 * Constructs a <code>SimpleQuantityFormat</code> using the given pattern. 072 * <p> 073 * 074 * @param pattern 075 * the pattern describing the quantity and unit format 076 * @exception NullPointerException 077 * if the given pattern is null 078 * @exception IllegalArgumentException 079 * if the given pattern is invalid 080 */ 081 public SimpleQuantityFormat(String pattern) { 082 this.pattern = pattern; 083 } 084 085 /** 086 * Constructs a <code>SimpleQuantityFormat</code> using the default pattern. For 087 * full coverage, use the factory methods. 088 */ 089 public SimpleQuantityFormat() { 090 this(""); 091 } 092 093 @Override 094 public Appendable format(Quantity quantity, Appendable dest) throws IOException { 095 Unit unit = quantity.getUnit(); 096 097 dest.append(quantity.getValue().toString()); 098 if (quantity.getUnit().equals(AbstractUnit.ONE)) 099 return dest; 100 dest.append(' '); 101 return SimpleUnitFormat.getInstance().format(unit, dest); 102 } 103 104 @SuppressWarnings("unchecked") 105 @Override 106 public ComparableQuantity<?> parse(CharSequence csq, ParsePosition cursor) throws MeasurementParseException { 107 int startDecimal = cursor.getIndex(); 108 while ((startDecimal < csq.length()) && Character.isWhitespace(csq.charAt(startDecimal))) { 109 startDecimal++; 110 } 111 int endDecimal = startDecimal + 1; 112 while ((endDecimal < csq.length()) && !Character.isWhitespace(csq.charAt(endDecimal))) { 113 endDecimal++; 114 } 115 BigDecimal decimal = new BigDecimal(csq.subSequence(startDecimal, endDecimal).toString()); 116 cursor.setIndex(endDecimal + 1); 117 Unit unit = SimpleUnitFormat.getInstance().parse(csq, cursor); 118 return Quantities.getQuantity(decimal, unit); 119 } 120 121 @SuppressWarnings("unchecked") 122 @Override 123 AbstractQuantity<?> parse(CharSequence csq, int index) throws MeasurementParseException { 124 int startDecimal = index; // cursor.getIndex(); 125 while ((startDecimal < csq.length()) && Character.isWhitespace(csq.charAt(startDecimal))) { 126 startDecimal++; 127 } 128 int endDecimal = startDecimal + 1; 129 while ((endDecimal < csq.length()) && !Character.isWhitespace(csq.charAt(endDecimal))) { 130 endDecimal++; 131 } 132 Double decimal = new Double(csq.subSequence(startDecimal, endDecimal).toString()); 133 Unit unit = SimpleUnitFormat.getInstance().parse(csq, index); 134 return NumberQuantity.of(decimal, unit); 135 } 136 137 @Override 138 public ComparableQuantity<?> parse(CharSequence csq) throws MeasurementParseException { 139 return parse(csq, new ParsePosition(0)); 140 } 141 142 /** 143 * Returns the quantity format for the default locale. The default format 144 * assumes the quantity is composed of a decimal number and a {@link Unit} 145 * separated by whitespace(s). 146 * 147 * @return <code>MeasureFormat.getInstance(NumberFormat.getInstance(), UnitFormat.getInstance())</code> 148 */ 149 public static SimpleQuantityFormat getInstance() { 150 return DEFAULT; 151 } 152 153 /** 154 * Returns a <code>SimpleQuantityFormat</code> using the given pattern. 155 * <p> 156 * 157 * @param pattern 158 * the pattern describing the quantity and unit format 159 * 160 * @return <code>MeasureFormat.getInstance(NumberFormat.getInstance(), UnitFormat.getInstance())</code> 161 */ 162 public static SimpleQuantityFormat getInstance(String pattern) { 163 return new SimpleQuantityFormat(pattern); 164 } 165 166 public String getPattern() { 167 return pattern; 168 } 169}