/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 net.hasor.core.convert.convert;
import net.hasor.core.convert.ConversionException;
import net.hasor.core.convert.Converter;
import java.lang.reflect.Array;
import java.util.Collection;
/**
* Base {@link Converter} implementation that provides the structure
* for handling conversion <b>to</b> and <b>from</b> a specified type.
* <p>
* This implementation provides the basic structure for
* converting to/from a specified type optionally using a default
* value or throwing a {@link ConversionException} if a
* conversion error occurs.
* <p>
* Implementations should provide conversion to the specified
* type and from the specified type to a <code>String</code> value
* by implementing the following methods:
* <ul>
* <li><code>convertToString(value)</code> - convert to a String
* (default implementation uses the objects <code>toString()</code>
* method).</li>
* <li><code>convertToType(Class, value)</code> - convert
* to the specified type</li>
* </ul>
*
* @version $Revision: 640131 $ $Date: 2008-03-23 02:10:31 +0000 (Sun, 23 Mar 2008) $
* @since 1.8.0
*/
@SuppressWarnings({ "rawtypes" })
public abstract class AbstractConverter implements Converter {
/** 当转换出错时是否返回默认值。*/
private boolean useDefault = false;
/**默认值*/
private Object defaultValue = null;
// ----------------------------------------------------------- Constructors
/**创建创造<i>Converter</i>转换器,可能会引发<code>ConversionException</code>异常。*/
public AbstractConverter() {
}
/**创建创造<i>Converter</i>转换器,可能会引发<code>ConversionException</code>异常。*/
public AbstractConverter(final Object defaultValue) {
this.setDefaultValue(defaultValue);
}
// --------------------------------------------------------- Public Methods
/**
* 当转换期间发生异常时是否使用默认值。
* @return 如果<code>true</code>则表示当遇到错误时设置的默认值会被返回。如果<code>false</code>会引发{@link ConversionException}异常。
*/
public boolean isUseDefault() {
return this.useDefault;
}
/**
* Convert the input object into an output object of the
* specified type.
*
* @param type Data type to which this value should be converted
* @param value The input value to be converted
* @return The converted value.
* @throws ConversionException if conversion cannot be performed
* successfully and no default is specified.
*/
@Override
public Object convert(final Class type, Object value) {
Class sourceType = value == null ? null : value.getClass();
Class targetType = this.primitive(type == null ? this.getDefaultType() : type);
value = this.convertArray(value);//如果数据源是一个Array 或 集合 那么取得第一个元素。
//Missing Value
if (value == null) {
return this.handleMissing(targetType);
}
//
sourceType = value.getClass();
try {
/*Convert --> String*/
if (targetType.equals(String.class)) {
return this.convertToString(value);
} else if (targetType.equals(sourceType)) {
return value;
/*Convert --> Type*/
} else {
return this.convertToType(targetType, value);
}
} catch (Throwable t) {
return this.handleError(targetType, value, t);
}
}
/**
* 处理转换错误。<p>
* 如果设置了default属性则当遇到错误时返回默认值。否则引发{@link ConversionException}异常。
*/
protected Object handleError(final Class type, final Object value, final Throwable cause) {
if (this.useDefault) {
return this.handleMissing(type);
}
if (cause instanceof ConversionException) {
throw (ConversionException) cause;
} else {
String msg = "Error converting from '" + value.getClass() + "' to '" + type + "' " + cause.getMessage();
throw new ConversionException(msg, cause);
}
}
/**
* 转换对象成为String格式。<p>
* <b>注意:</b>这个方法简单使用<code>toString()</code>实现该功能,子类应当重写该方法以完成特殊的转换过程。
*/
protected String convertToString(final Object value) throws Throwable {
return value.toString();
}
/**执行类型转换代码。*/
protected abstract Object convertToType(Class type, Object value) throws Throwable;
/**
* Return the first element from an Array (or Collection)
* or the value unchanged if not an Array (or Collection).
*
* N.B. This needs to be overriden for array/Collection converters.
*
* @param value The value to convert
* @return The first element in an Array (or Collection)
* or the value unchanged if not an Array (or Collection)
*/
protected Object convertArray(final Object value) {
if (value == null) {
return null;
}
if (value.getClass().isArray()) {
if (Array.getLength(value) > 0) {
return Array.get(value, 0);
} else {
return null;
}
}
if (value instanceof Collection) {
Collection collection = (Collection) value;
if (collection.size() > 0) {
return collection.iterator().next();
} else {
return null;
}
}
return value;
}
/**设置默认值 */
protected void setDefaultValue(final Object defaultValue) {
this.useDefault = false;
if (defaultValue == null) {
this.defaultValue = null;
} else {
this.defaultValue = this.convert(this.getDefaultType(), defaultValue);
}
this.useDefault = true;
}
/**获取默认值*/
protected abstract Class getDefaultType();
/**返回指定类型的默认值.*/
protected Object getDefault(final Class type) {
if (type.equals(String.class)) {
return null;
} else {
return this.defaultValue;
}
}
/**
* Provide a String representation of this converter.
* @return A String representation of this converter
*/
@Override
public String toString() {
return this.toString(this.getClass()) + "[UseDefault=" + this.useDefault + "]";
}
/**当遇到空值传入或者返回值为空的时候*/
protected Object handleMissing(final Class type) {
if (this.useDefault || type.equals(String.class)) {
Object value = this.getDefault(type);
if (this.useDefault && value != null && !type.equals(value.getClass())) {
try {
value = this.convertToType(type, this.defaultValue);
} catch (Throwable t) {
//log().error(" Default conversion to " + toString(type) + "failed: " + t);// TODO Log
}
}
return value;
}
throw new ConversionException("No value specified for '" + this.toString(type) + "'");
}
// ----------------------------------------------------------- Package Methods
/** 转换基本类型到包装类型. */
private Class primitive(final Class type) {
if (type == null || !type.isPrimitive()) {
return type;
}
if (type == Integer.TYPE) {
return Integer.class;
} else if (type == Double.TYPE) {
return Double.class;
} else if (type == Long.TYPE) {
return Long.class;
} else if (type == Boolean.TYPE) {
return Boolean.class;
} else if (type == Float.TYPE) {
return Float.class;
} else if (type == Short.TYPE) {
return Short.class;
} else if (type == Byte.TYPE) {
return Byte.class;
} else if (type == Character.TYPE) {
return Character.class;
} else {
return type;
}
}
//
//
/**
* Provide a String representation of a <code>java.lang.Class</code>.
* @param type The <code>java.lang.Class</code>.
* @return The String representation.
*/
public String toString(final Class type) {
String typeName = null;
if (type == null) {
typeName = "null";
} else if (type.isArray()) {
Class elementType = type.getComponentType();
int count = 1;
while (elementType.isArray()) {
elementType = elementType.getComponentType();
count++;
}
typeName = elementType.getName();
for (int i = 0; i < count; i++) {
typeName += "[]";
}
} else {
typeName = type.getName();
}
/* org.more.convert.convert. */
final String PACKAGE = AbstractConverter.class.getPackage().getName() + ".";
if (typeName.startsWith("java.lang.") || typeName.startsWith("java.util.") || typeName.startsWith("java.math.")) {
typeName = typeName.substring("java.lang.".length());
} else if (typeName.startsWith(PACKAGE)) {
typeName = typeName.substring(PACKAGE.length());
}
return typeName;
}
}