/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.citrus.service.form.support;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.ObjectUtil.*;
import static com.alibaba.citrus.util.StringUtil.*;
import java.beans.PropertyEditorSupport;
import java.math.BigDecimal;
import java.util.regex.Pattern;
import com.alibaba.citrus.util.StringUtil;
/**
* 用来方便各种类型数字的比较操作。
*
* @author Michael Zhou
*/
public class NumberSupport implements Comparable<NumberSupport> {
private String stringValue;
private Number numberValue;
private Type numberType;
public NumberSupport() {
}
public NumberSupport(Type numberType, String stringValue) {
setNumberType(numberType);
setStringValue(stringValue);
}
public String getStringValue() {
return stringValue;
}
public void setStringValue(String stringValue) {
this.stringValue = trimToNull(stringValue);
}
public Type getNumberType() {
return numberType;
}
public void setNumberType(Type numberType) {
this.numberType = numberType;
}
public Number getValue() throws NumberFormatException, IllegalArgumentException {
assertNotNull(numberType, "no number type specified");
assertNotNull(stringValue, "no value set");
if (numberValue == null) {
numberValue = numberType.parse(stringValue);
}
return numberValue;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public int compareTo(NumberSupport n) {
Number v1 = getValue();
Number v2 = n.getValue();
assertTrue(v1 instanceof Comparable<?>, "not comparable number: %s", v1);
return ((Comparable) v1).compareTo(v2);
}
@Override
public int hashCode() {
return 31 + getValue().hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (obj instanceof NumberSupport && getNumberType() == ((NumberSupport) obj).getNumberType()) {
return compareTo((NumberSupport) obj) == 0;
}
return false;
}
@Override
public String toString() {
return numberValue == null ? stringValue : numberValue.toString();
}
/** 数字的类型。 */
public static enum Type {
INT {
@Override
public Number parse(String value) {
return Integer.parseInt(value);
}
},
LONG {
@Override
public Number parse(String value) {
return Long.parseLong(value);
}
},
FLOAT {
@Override
public Number parse(String value) {
return Float.parseFloat(value);
}
},
DOUBLE {
@Override
public Number parse(String value) {
return Double.parseDouble(value);
}
},
BIG_DECIMAL {
@Override
public Number parse(String value) {
if (value == null || !numberPattern.matcher(value).matches()) {
throw new NumberFormatException(value);
}
return new BigDecimal(value);
}
};
private final static Pattern numberPattern = Pattern.compile("(\\+|-)?[\\d\\.]+");
public static Type byName(String name) {
name = defaultIfNull(trimToNull(name), "INT");
String typeName = StringUtil.toUpperCaseWithUnderscores(name);
try {
return Type.valueOf(typeName);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("wrong number type: " + name);
}
}
public abstract Number parse(String value) throws NumberFormatException;
}
public static class TypeEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(Type.byName(text));
}
}
}