blob: c2e206fcfb204cc688425c0ad505936db69c9628 [file] [log] [blame]
package org.unicode.cldr.util;
import java.util.Iterator;
import org.unicode.cldr.util.SupplementalDataInfo.UnitIdComponentType;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.ibm.icu.util.Output;
public class UnitParser {
private static final CLDRConfig CLDR_CONFIG = CLDRConfig.getInstance();
private static final CLDRConfig info = CLDR_CONFIG;
private static final SupplementalDataInfo SDI = info.getSupplementalDataInfo();
public static final Splitter DASH_SPLITTER = Splitter.on('-');
public static final Joiner DASH_JOIN = Joiner.on('-');
private String bufferedItem = null;
private UnitIdComponentType bufferedType = null;
private Iterator<String> source;
public UnitParser set(Iterator<String> source) {
bufferedItem = null;
this.source = source;
return this;
}
public UnitParser set(Iterable<String> source) {
return set(source.iterator());
}
public UnitParser set(String source) {
return set(UnitParser.DASH_SPLITTER.split(source).iterator());
}
private enum State {start, havePrefix, haveBaseOrSuffix}
/**
* Parses the next segment in the source from set.
* @param output returns type type of the item, where base is for prefix* base suffix*
* @return a unit segment of the form: prefix* base suffix*, and, per, or power
*/
public String nextParse(Output<UnitIdComponentType> type) {
String output = null;
State state = State.start;
UnitIdComponentType outputType = null;
while (true) {
if (bufferedItem == null) {
if (!source.hasNext()) {
break;
}
bufferedItem = source.next();
bufferedType = SDI.getUnitIdComponentType(bufferedItem);
}
switch(bufferedType) {
case prefix:
switch(state) {
case start:
state = State.havePrefix;
break;
case havePrefix: // ok, continue
break;
case haveBaseOrSuffix:
type.value = outputType == UnitIdComponentType.suffix ? UnitIdComponentType.base : outputType;
return output;
}
break;
case base:
switch(state) {
case start:
case havePrefix:
state = State.haveBaseOrSuffix;
break;
case haveBaseOrSuffix: // have stuff to return
type.value = outputType == UnitIdComponentType.suffix ? UnitIdComponentType.base : outputType;
return output;
}
break;
case suffix:
switch(state) {
case start:
case havePrefix:
throw new IllegalArgumentException("Unit suffix must follow base: " + output + " ❌ " + bufferedItem);
case haveBaseOrSuffix: // ok, continue
break;
}
break;
case and:
case per:
case power:
switch(state) {
case start: // return this item
output = bufferedItem;
bufferedItem = null;
type.value = outputType;
return output;
case havePrefix:
throw new IllegalArgumentException("Unit prefix must be followed with base: " + output + " ❌ " + bufferedItem);
case haveBaseOrSuffix: // have stuff to return
type.value = outputType == UnitIdComponentType.suffix ? UnitIdComponentType.base : outputType;
return output;
}
break;
}
output = output == null ? bufferedItem : output + "-" + bufferedItem;
bufferedItem = null;
outputType = bufferedType;
}
switch(state) {
default:
case start:
return null;
case havePrefix:
throw new IllegalArgumentException("Unit prefix must be followed with base: " + output + " ❌ " + bufferedItem);
case haveBaseOrSuffix: // have stuff to return
type.value = outputType == UnitIdComponentType.suffix ? UnitIdComponentType.base : outputType;
return output;
}
}
// TODO create from custom map
public UnitIdComponentType getUnitIdComponentType(String part) {
return SDI.getUnitIdComponentType(part);
}
}