• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.unicode.cldr.util;
2 
3 import java.util.Iterator;
4 
5 import org.unicode.cldr.util.SupplementalDataInfo.UnitIdComponentType;
6 
7 import com.google.common.base.Joiner;
8 import com.google.common.base.Splitter;
9 import com.ibm.icu.util.Output;
10 
11 public class UnitParser {
12     private static final CLDRConfig CLDR_CONFIG = CLDRConfig.getInstance();
13     private static final CLDRConfig info = CLDR_CONFIG;
14     private static final SupplementalDataInfo SDI = info.getSupplementalDataInfo();
15     public static final Splitter DASH_SPLITTER = Splitter.on('-');
16     public static final Joiner DASH_JOIN = Joiner.on('-');
17 
18     private String bufferedItem = null;
19     private UnitIdComponentType bufferedType = null;
20     private Iterator<String> source;
21 
set(Iterator<String> source)22     public UnitParser set(Iterator<String> source) {
23         bufferedItem = null;
24         this.source = source;
25         return this;
26     }
27 
set(Iterable<String> source)28     public UnitParser set(Iterable<String> source) {
29         return set(source.iterator());
30     }
31 
set(String source)32     public UnitParser set(String source) {
33         return set(UnitParser.DASH_SPLITTER.split(source).iterator());
34     }
35 
36     private enum State {start, havePrefix, haveBaseOrSuffix}
37 
38     /**
39      * Parses the next segment in the source from set.
40      * @param output returns type type of the item, where base is for prefix* base suffix*
41      * @return a unit segment of the form: prefix* base suffix*, and, per, or power
42      */
nextParse(Output<UnitIdComponentType> type)43     public String nextParse(Output<UnitIdComponentType> type) {
44         String output = null;
45         State state = State.start;
46         UnitIdComponentType outputType = null;
47 
48         while (true) {
49             if (bufferedItem == null) {
50                 if (!source.hasNext()) {
51                     break;
52                 }
53                 bufferedItem = source.next();
54                 bufferedType = SDI.getUnitIdComponentType(bufferedItem);
55             }
56             switch(bufferedType) {
57             case prefix:
58                 switch(state) {
59                 case start:
60                     state = State.havePrefix;
61                     break;
62                 case havePrefix: // ok, continue
63                     break;
64                 case haveBaseOrSuffix:
65                     type.value = outputType == UnitIdComponentType.suffix ? UnitIdComponentType.base : outputType;
66                     return output;
67                 }
68                 break;
69             case base:
70                 switch(state) {
71                 case start:
72                 case havePrefix:
73                     state = State.haveBaseOrSuffix;
74                     break;
75                 case haveBaseOrSuffix: // have stuff to return
76                     type.value = outputType == UnitIdComponentType.suffix ? UnitIdComponentType.base : outputType;
77                     return output;
78                 }
79                 break;
80             case suffix:
81                 switch(state) {
82                 case start:
83                 case havePrefix:
84                     throw new IllegalArgumentException("Unit suffix must follow base: " + output + " ❌ " + bufferedItem);
85                 case haveBaseOrSuffix: // ok, continue
86                     break;
87                 }
88                 break;
89             case and:
90             case per:
91             case power:
92                 switch(state) {
93                 case start: // return this item
94                     output = bufferedItem;
95                     bufferedItem = null;
96                     type.value = outputType;
97                     return output;
98                 case havePrefix:
99                     throw new IllegalArgumentException("Unit prefix must be followed with base: " + output + " ❌ " + bufferedItem);
100                 case haveBaseOrSuffix: // have stuff to return
101                     type.value = outputType == UnitIdComponentType.suffix ? UnitIdComponentType.base : outputType;
102                     return output;
103                 }
104                 break;
105             }
106             output = output == null ? bufferedItem : output + "-" + bufferedItem;
107             bufferedItem = null;
108             outputType = bufferedType;
109         }
110         switch(state) {
111         default:
112         case start:
113             return null;
114         case havePrefix:
115             throw new IllegalArgumentException("Unit prefix must be followed with base: " + output + " ❌ " + bufferedItem);
116         case haveBaseOrSuffix: // have stuff to return
117             type.value = outputType == UnitIdComponentType.suffix ? UnitIdComponentType.base : outputType;
118             return output;
119         }
120     }
121 
122     // TODO create from custom map
getUnitIdComponentType(String part)123     public UnitIdComponentType getUnitIdComponentType(String part) {
124         return SDI.getUnitIdComponentType(part);
125     }
126 }
127