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.text.FieldPosition; 034import java.text.Format; 035import java.text.ParsePosition; 036 037import javax.measure.Quantity; 038import javax.measure.format.MeasurementParseException; 039import javax.measure.format.QuantityFormat; 040import tech.units.indriya.AbstractQuantity; 041import tech.units.indriya.ComparableQuantity; 042import tech.uom.lib.common.function.Parser; 043 044/** 045 * <p> 046 * This class provides the interface for formatting and parsing {@link Quantity quantities}. 047 * </p> 048 * 049 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 050 * @author <a href="mailto:werner@uom.technology">Werner Keil</a> 051 * @version 1.1, $Date: 2018-04-06 $ 052 * @since 1.0 053 * 054 */ 055@SuppressWarnings("rawtypes") 056public abstract class AbstractQuantityFormat extends Format implements QuantityFormat, Parser<CharSequence, ComparableQuantity> { 057 // TODO for later, see https://github.com/unitsofmeasurement/indriya/issues/17 058 // * <p> 059 // * Instances of this class should be able to format quantities stated in {@link CompoundUnit}. See {@link #formatCompound formatCompound(...)}. 060 // * </p> 061 062 /** 063 * 064 */ 065 private static final long serialVersionUID = -4628006924354248662L; 066 067 /** 068 * Formats the specified quantity into an <code>Appendable</code>. 069 * 070 * @param quantity 071 * the quantity to format. 072 * @param dest 073 * the appendable destination. 074 * @return the specified <code>Appendable</code>. 075 * @throws IOException 076 * if an I/O exception occurs. 077 */ 078 public abstract Appendable format(Quantity<?> quantity, Appendable dest) throws IOException; 079 080 /** 081 * Parses a portion of the specified <code>CharSequence</code> from the specified position to produce an object. If parsing succeeds, then the index 082 * of the <code>cursor</code> argument is updated to the index after the last character used. 083 * 084 * @param csq 085 * the <code>CharSequence</code> to parse. 086 * @param cursor 087 * the cursor holding the current parsing index. 088 * @return the object parsed from the specified character sub-sequence. 089 * @throws IllegalArgumentException 090 * if any problem occurs while parsing the specified character sequence (e.g. illegal syntax). 091 */ 092 public abstract ComparableQuantity<?> parse(CharSequence csq, ParsePosition cursor) throws IllegalArgumentException, MeasurementParseException; 093 094 /** 095 * Parses a portion of the specified <code>CharSequence</code> from the specified position to produce an object. If parsing succeeds, then the index 096 * of the <code>cursor</code> argument is updated to the index after the last character used. 097 * 098 * @param csq 099 * the <code>CharSequence</code> to parse. 100 * @param cursor 101 * the cursor holding the current parsing index. 102 * @return the object parsed from the specified character sub-sequence. 103 * @throws IllegalArgumentException 104 * if any problem occurs while parsing the specified character sequence (e.g. illegal syntax). 105 */ 106 @Override 107 public abstract ComparableQuantity<?> parse(CharSequence csq) throws MeasurementParseException; 108 109 /** 110 * Parses a portion of the specified <code>CharSequence</code> from the specified position to produce an object. If parsing succeeds, then the index 111 * of the <code>cursor</code> argument is updated to the index after the last character used. 112 * 113 * @param csq 114 * the <code>CharSequence</code> to parse. 115 * @param index 116 * the current parsing index. 117 * @return the object parsed from the specified character sub-sequence. 118 * @throws IllegalArgumentException 119 * if any problem occurs while parsing the specified character sequence (e.g. illegal syntax). 120 */ 121 abstract ComparableQuantity<?> parse(CharSequence csq, int index) throws IllegalArgumentException, MeasurementParseException; 122 123 @Override 124 public final StringBuffer format(Object obj, final StringBuffer toAppendTo, FieldPosition pos) { 125 if (!(obj instanceof AbstractQuantity<?>)) 126 throw new IllegalArgumentException("obj: Not an instance of Quantity"); 127 if ((toAppendTo == null) || (pos == null)) 128 throw new NullPointerException(); 129 try { 130 return (StringBuffer) format((AbstractQuantity<?>) obj, toAppendTo); 131 } catch (IOException ex) { 132 throw new Error(ex); // Cannot happen. 133 } 134 } 135 136 @Override 137 public final Quantity<?> parseObject(String source, ParsePosition pos) { 138 try { 139 return parse(source, pos); 140 } catch (IllegalArgumentException | MeasurementParseException e) { 141 return null; 142 } 143 } 144 145 /** 146 * Convenience method equivalent to {@link #format(AbstractQuantity, Appendable)} except it does not raise an IOException. 147 * 148 * @param quantity 149 * the quantity to format. 150 * @param dest 151 * the appendable destination. 152 * @return the specified <code>StringBuilder</code>. 153 */ 154 public final StringBuilder format(AbstractQuantity<?> quantity, StringBuilder dest) { 155 try { 156 return (StringBuilder) this.format(quantity, (Appendable) dest); 157 } catch (IOException ex) { 158 throw new RuntimeException(ex); // Should not happen. 159 } 160 } 161}