001/* 002 * Units of Measurement Systems 003 * Copyright (c) 2005-2021, Jean-Marie Dautelle, Werner Keil and others. 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, Units of Measurement nor the names of their contributors may be used to 017 * endorse or promote products 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 systems.uom.ucum.spi; 031 032import static tech.units.indriya.format.FormatBehavior.LOCALE_SENSITIVE; 033 034import java.text.NumberFormat; 035import java.util.HashMap; 036import java.util.Locale; 037import java.util.Map; 038import java.util.Objects; 039import java.util.Set; 040 041import javax.measure.format.QuantityFormat; 042import javax.measure.format.UnitFormat; 043import javax.measure.spi.FormatService; 044import systems.uom.ucum.format.UCUMFormat; 045import systems.uom.ucum.format.UCUMFormat.Variant; 046import tech.units.indriya.format.EBNFUnitFormat; 047import tech.units.indriya.format.NumberDelimiterQuantityFormat; 048import tech.units.indriya.format.SimpleQuantityFormat; 049 050/** 051 * UCUM format service. 052 * 053 * @author Werner Keil 054 * @version 2.0, November 18, 2020 055 */ 056public final class UCUMFormatService implements FormatService { 057 058 private static final String UNIT_FORMAT_KEY_CASE_SENSITIVE = "UCUM_CS"; 059 private static final String UNIT_FORMAT_KEY_CASE_INSENSITIVE = "UCUM_CI"; 060 private static final String UNIT_FORMAT_KEY_PRINT = "UCUM_PRINT"; 061 private static final String DEFAULT_UNIT_FORMAT = UNIT_FORMAT_KEY_CASE_SENSITIVE; 062 063 private final Map<String, UnitFormat> unitFormats = new HashMap<>(); 064 private final Map<String, String> unitFormatAliases = new HashMap<>(); 065 066 private static final String DEFAULT_QUANTITY_FORMAT = "Simple"; 067 068 /** 069 * Holds the default format instance (EBNFUnitFormat). 070 */ 071 private static final NumberDelimiterQuantityFormat EBNF_QUANTITY_FORMAT = new NumberDelimiterQuantityFormat.Builder() 072 .setNumberFormat(NumberFormat.getInstance(Locale.ROOT)).setUnitFormat(EBNFUnitFormat.getInstance()).build(); 073 074 private final Map<String, QuantityFormat> quantityFormats = new HashMap<>(); 075 076 public UCUMFormatService() { 077 quantityFormats.put(DEFAULT_QUANTITY_FORMAT, SimpleQuantityFormat.getInstance()); 078 quantityFormats.put("NumberDelimiter", NumberDelimiterQuantityFormat.getInstance()); 079 quantityFormats.put("EBNF", EBNF_QUANTITY_FORMAT); 080 quantityFormats.put("Local", NumberDelimiterQuantityFormat.getInstance(LOCALE_SENSITIVE)); 081 082 unitFormats.put(DEFAULT_UNIT_FORMAT, UCUMFormat.getInstance(Variant.CASE_SENSITIVE)); 083 unitFormats.put(UNIT_FORMAT_KEY_CASE_INSENSITIVE, UCUMFormat.getInstance(Variant.CASE_INSENSITIVE)); 084 unitFormats.put(UNIT_FORMAT_KEY_PRINT, UCUMFormat.getInstance(Variant.PRINT)); 085 086 unitFormatAliases.put("UCUM", DEFAULT_UNIT_FORMAT); 087 unitFormatAliases.put(Variant.CASE_SENSITIVE.name(), DEFAULT_UNIT_FORMAT); 088 unitFormatAliases.put(Variant.CASE_INSENSITIVE.name(), UNIT_FORMAT_KEY_CASE_INSENSITIVE); 089 unitFormatAliases.put(Variant.PRINT.name(), UNIT_FORMAT_KEY_PRINT); 090 unitFormatAliases.put("CS", DEFAULT_UNIT_FORMAT); 091 unitFormatAliases.put("C/S", DEFAULT_UNIT_FORMAT); 092 unitFormatAliases.put("CASE SENSITIVE", DEFAULT_UNIT_FORMAT); 093 unitFormatAliases.put("CI", UNIT_FORMAT_KEY_CASE_INSENSITIVE); 094 unitFormatAliases.put("C/I", UNIT_FORMAT_KEY_CASE_INSENSITIVE); 095 unitFormatAliases.put("CASE INSENSITIVE", UNIT_FORMAT_KEY_CASE_INSENSITIVE); 096 } 097 098 /* 099 * (non-Javadoc) 100 * 101 * @see UnitFormatService#getUnitFormat(String) 102 */ 103 @Override 104 public UnitFormat getUnitFormat(String key) { 105 Objects.requireNonNull(key, "Format name or alias required"); 106 String alias = unitFormatAliases.get(key.toUpperCase()); 107 if (alias != null && alias.length() > 0) { 108 return unitFormats.get(alias); 109 } 110 return unitFormats.get(key.toUpperCase()); 111 } 112 113 /* 114 * (non-Javadoc) 115 * 116 * @see UnitFormatService#getUnitFormat() 117 */ 118 @Override 119 public UnitFormat getUnitFormat() { 120 return getUnitFormat(DEFAULT_UNIT_FORMAT); 121 } 122 123 public Set<String> getAvailableFormatNames() { 124 return unitFormats.keySet(); 125 } 126 127 @Override 128 public QuantityFormat getQuantityFormat(String name) { 129 return quantityFormats.get(name); 130 } 131 132 @Override 133 public QuantityFormat getQuantityFormat() { 134 return getQuantityFormat(DEFAULT_QUANTITY_FORMAT); 135 } 136 137 @Override 138 public Set<String> getAvailableFormatNames(FormatType type) { 139 switch (type) { 140 case QUANTITY_FORMAT: 141 return quantityFormats.keySet(); 142 default: 143 return unitFormats.keySet(); 144 } 145 } 146 147 @Override 148 public UnitFormat getUnitFormat(String name, String variant) { 149 final StringBuilder sb = new StringBuilder(name); 150 if (null != variant && !variant.isEmpty()) { 151 sb.append("_"); 152 sb.append(variant); 153 } 154 return getUnitFormat(sb.toString()); 155 } 156}