package jef.database.routing.function;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import jef.common.ContinuedRange;
import jef.database.annotation.PartitionFunction;
import jef.database.query.RegexpDimension;
import org.apache.commons.lang.StringUtils;
public class MapFunction implements PartitionFunction<String>{
private final List<StringRange> ranges = new ArrayList<StringRange>();
private String defaultTarget="";
private int maxLen;
private List<String> allValues=new ArrayList<String>();
public MapFunction(String expression,int digit){
this.maxLen=digit>0?digit:20;
for(String s:StringUtils.split(expression,",")){
int index=s.lastIndexOf(':');
if(index<1){
throw new IllegalArgumentException("Invalid config of map:"+s);
}
String value=s.substring(index+1);
s=s.substring(0,index);
if("*".equals(s)){
defaultTarget=value;
}else{
index=s.lastIndexOf('-');
if(index>0){ //如果第一位就是-,认为是负号,不算分隔符
ranges.add(new StringRange(s.substring(0,index),s.substring(index+1)).setTarget(value));
}else{
ranges.add(new Single(s).setTarget(value));
}
}
}
Collections.sort(ranges,new Comparator<StringRange>() {//必须按小到大排序
public int compare(StringRange o1, StringRange o2) {
return o1.getStart().compareTo(o2.getStart());
}
});
for(StringRange range:ranges){
allValues.add(range.getStart());
}
}
public String eval(String value) {
if(value.length()>maxLen){
value=value.substring(0,maxLen);
}
for(StringRange range:ranges){
if(range.contains(value)){
return range.target;
}
}
return defaultTarget;
}
//TODO 这个方法要单元测试一下
public List<String> iterator(String min, String max, boolean left, boolean right) {
if(min==null && max==null){
return allValues;
}
List<String> result=new ArrayList<String>();
boolean open=false;
if(min==null){
open=true;
}else if(left){
result.add(min);
}
for(StringRange range:ranges){
if(open){
if(range.contains(max)){
open=false;
break;
}else{
result.add(range.start);
}
}else{
if(range.contains(min)){
open=true;
if(range.contains(max)){
open=false;
break;
}
}
}
}
if(max!=null && !max.equals(min) && right){
result.add(max);
}
return result;
}
@SuppressWarnings("serial")
private static class StringRange extends ContinuedRange<String>{
protected String start;
private String end;
private String target;
public StringRange setTarget(String target) {
this.target = target;
return this;
}
public StringRange(String start, String end) {
this.start=start;
this.end=end;
}
@Override
public String getEnd() {
return end;
}
@Override
public String getStart() {
return start;
}
@Override
public void extendTo(String obj) {
throw new UnsupportedOperationException();
}
@Override
public boolean isEndIndexInclusive() {
return true;
}
@Override
public boolean isBeginIndexInclusive() {
return true;
}
}
@SuppressWarnings("serial")
private static final class Single extends StringRange{
public Single(String s) {
super(s,s);
}
public boolean contains(String obj) {
return start.equals(obj);
}
}
public boolean acceptRegexp() {
return false;
}
public Collection<String> iterator(RegexpDimension regexp) {
throw new UnsupportedOperationException();
}
}