1 package org.unicode.cldr.util; 2 3 import com.google.common.collect.BiMap; 4 import com.google.common.collect.ImmutableBiMap; 5 import com.google.common.collect.ImmutableMap; 6 import com.google.common.collect.ImmutableMultimap; 7 import com.google.common.collect.Multimap; 8 import com.google.common.collect.TreeMultimap; 9 import com.ibm.icu.text.MessageFormat; 10 import com.ibm.icu.text.UnicodeSet; 11 import com.ibm.icu.text.UnicodeSetSpanner; 12 import java.util.Collection; 13 import java.util.Locale; 14 import java.util.Map; 15 import java.util.Set; 16 import java.util.TreeMap; 17 import java.util.regex.Pattern; 18 import org.unicode.cldr.test.ExampleGenerator; 19 import org.unicode.cldr.util.StandardCodes.LstrType; 20 import org.unicode.cldr.util.Validity.Status; 21 22 public class Units { 23 24 private static final UnicodeSet WHITESPACE = new UnicodeSet("[:whitespace:]").freeze(); 25 public static Pattern NO_SPACE_PREFIX = 26 Pattern.compile( 27 "\\}" 28 + ExampleGenerator.backgroundEndSymbol 29 + "?\\p{L}|\\p{L}" 30 + ExampleGenerator.backgroundStartSymbol 31 + "?\\{"); 32 combinePattern( String unitFormat, String compoundPattern, boolean lowercaseUnitIfNoSpaceInCompound)33 public static String combinePattern( 34 String unitFormat, String compoundPattern, boolean lowercaseUnitIfNoSpaceInCompound) { 35 // meterFormat of the form {0} meters or {0} Meter 36 // compoundPattern is of the form Z{0} or Zetta{0} 37 38 // extract the unit 39 String modUnit = (String) SPACE_SPANNER.trim(unitFormat.replace("{0}", "")); 40 Object[] parameters = {modUnit}; 41 42 String modFormat = 43 unitFormat.replace(modUnit, MessageFormat.format(compoundPattern, parameters)); 44 if (modFormat.equals(unitFormat)) { 45 // didn't work, so fall back 46 Object[] parameters1 = {unitFormat}; 47 modFormat = MessageFormat.format(compoundPattern, parameters1); 48 } 49 50 // hack to fix casing 51 if (lowercaseUnitIfNoSpaceInCompound && NO_SPACE_PREFIX.matcher(compoundPattern).find()) { 52 modFormat = modFormat.replace(modUnit, modUnit.toLowerCase(Locale.ENGLISH)); 53 } 54 55 return modFormat; 56 } 57 58 static final UnicodeSetSpanner SPACE_SPANNER = new UnicodeSetSpanner(WHITESPACE); 59 60 public static final Map<String, String> CORE_TO_TYPE; 61 public static final Multimap<String, String> TYPE_TO_CORE; 62 public static final BiMap<String, String> LONG_TO_SHORT; 63 64 static { 65 Set<String> VALID_UNITS = 66 Validity.getInstance().getStatusToCodes(LstrType.unit).get(Status.regular); 67 68 Map<String, String> coreToType = new TreeMap<>(); 69 Multimap<String, String> typeToCore = TreeMultimap.create(); 70 Map<String, String> longToShort = new TreeMap<>(); 71 for (String s : VALID_UNITS) { 72 int dashPos = s.indexOf('-'); 73 String unitType = s.substring(0, dashPos); 74 String coreUnit = s.substring(dashPos + 1); longToShort.put(s, coreUnit)75 longToShort.put(s, coreUnit); 76 // coreUnit = converter.fixDenormalized(coreUnit); coreToType.put(coreUnit, unitType)77 coreToType.put(coreUnit, unitType); typeToCore.put(unitType, coreUnit)78 typeToCore.put(unitType, coreUnit); 79 } 80 CORE_TO_TYPE = ImmutableMap.copyOf(coreToType); 81 TYPE_TO_CORE = ImmutableMultimap.copyOf(typeToCore); 82 LONG_TO_SHORT = ImmutableBiMap.copyOf(longToShort); 83 } 84 85 public static class TypeAndCore { 86 public String type; 87 public String core; 88 } 89 /** 90 * Returns the type and core for a unit, be it long or short 91 * 92 * @param longOrShortUnit 93 * @param core 94 * @return 95 * @return 96 */ splitUnit(String longOrShortUnit, TypeAndCore typeAndCore)97 public static TypeAndCore splitUnit(String longOrShortUnit, TypeAndCore typeAndCore) { 98 int dashPos = longOrShortUnit.indexOf('-'); 99 String unitType = longOrShortUnit.substring(0, dashPos); 100 Collection<String> cores = TYPE_TO_CORE.get(unitType); 101 if (cores.isEmpty()) { // short unit 102 typeAndCore.type = CORE_TO_TYPE.get(longOrShortUnit); 103 typeAndCore.core = longOrShortUnit; 104 } else { 105 typeAndCore.type = unitType; 106 typeAndCore.core = longOrShortUnit.substring(dashPos + 1); 107 } 108 return typeAndCore; 109 } 110 getShort(String longUnit)111 public static String getShort(String longUnit) { 112 String result = LONG_TO_SHORT.get(longUnit); 113 return result == null ? longUnit : result; 114 } 115 getLong(String shortId)116 public static String getLong(String shortId) { 117 String result = LONG_TO_SHORT.inverse().get(shortId); 118 return result == null ? shortId : result; 119 } 120 } 121