/************************************************************************* * * ADOBE CONFIDENTIAL * __________________ * * Copyright 2002 - 2007 Adobe Systems Incorporated * All Rights Reserved. * * NOTICE: All information contained herein is, and remains * the property of Adobe Systems Incorporated and its suppliers, * if any. The intellectual and technical concepts contained * herein are proprietary to Adobe Systems Incorporated * and its suppliers and may be covered by U.S. and Foreign Patents, * patents in process, and are protected by trade secret or copyright law. * Dissemination of this information or reproduction of this material * is strictly forbidden unless prior written permission is obtained * from Adobe Systems Incorporated. **************************************************************************/ package cn.org.rapid_framework.flex.messaging.io.amf.translator.decoder; import java.math.BigDecimal; import java.math.BigInteger; import flex.messaging.io.SerializationContext; import flex.messaging.io.amf.translator.decoder.ActionScriptDecoder; import flex.messaging.io.amf.translator.decoder.DecoderFactory; /** * * 用于修正flex的number数据类型转换错误: NaN => 0 变为 NaN => null * * <br /> * Decode an ActionScript type (a string or a double) to a Java number (of any type). * * <br /> * <h3>使用方法:</h3> * 在services-config.xml中增加如下配置: * <pre> * <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel"> * <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/> * * <properties> * <serialization> * <type-marshaller>cn.org.rapid_framework.flex.messaging.io.CustomTypeMarshaller</type-marshaller> * </serialization> * </properties> * </channel-definition> * </pre> * @author badqiu */ public class NumberDecoder extends ActionScriptDecoder { public Object decodeObject(Object shell, Object encodedObject, Class desiredClass) { Object result = null; if (encodedObject != null && encodedObject instanceof String) { String str = ((String)encodedObject).trim(); try { // Short-ciruit String -> BigInteger,BigDecimal to avoid loss // of precision that occurs if we go through Double if (!SerializationContext.getSerializationContext().legacyBigNumbers) { if (BigInteger.class.equals(desiredClass)) { result = new BigInteger(str); return result; } else if (BigDecimal.class.equals(desiredClass)) { result = new BigDecimal(str); return result; } } Double dbl = new Double(str); encodedObject = dbl; } catch (NumberFormatException nfe) { DecoderFactory.invalidType(encodedObject, desiredClass); } } if (encodedObject instanceof Number || encodedObject == null) { Double dbl; if (desiredClass.isPrimitive()) { if (encodedObject == null) dbl = new Double(0); else dbl = new Double(((Number)encodedObject).doubleValue()); if ( dbl.equals(Double.NaN) ) result = null; else if (Object.class.equals(desiredClass) || Double.TYPE.equals(desiredClass)) result = dbl; else if (Integer.TYPE.equals(desiredClass)) result = new Integer(dbl.intValue()); else if (Long.TYPE.equals(desiredClass)) result = new Long(dbl.longValue()); else if (Float.TYPE.equals(desiredClass)) result = new Float(dbl.floatValue()); else if (Short.TYPE.equals(desiredClass)) result = new Short(dbl.shortValue()); else if (Byte.TYPE.equals(desiredClass)) result = new Byte(dbl.byteValue()); } else if (encodedObject != null) { dbl = new Double(((Number)encodedObject).doubleValue()); if ( dbl.equals(Double.NaN) ) result = null; else if (Object.class.equals(desiredClass) || Number.class.equals(desiredClass) || Double.class.equals(desiredClass)) result = dbl; else if (Integer.class.equals(desiredClass)) result = new Integer(dbl.intValue()); else if (Long.class.equals(desiredClass)) result = new Long(dbl.longValue()); else if (Float.class.equals(desiredClass)) result = new Float(dbl.floatValue()); else if (Short.class.equals(desiredClass)) result = new Short(dbl.shortValue()); else if (BigDecimal.class.equals(desiredClass)) { // Though this is a little slower than using the // double constructor for BigDecimal, it yields a rounded // result which is more predicable (see the Javadoc for // BigDecimal and bug: 182378). if (SerializationContext.getSerializationContext().legacyBigNumbers) result = new BigDecimal(dbl.doubleValue()); else result = new BigDecimal(String.valueOf(dbl)); } else if (Byte.class.equals(desiredClass)) result = new Byte(dbl.byteValue()); else if (BigInteger.class.equals(desiredClass)) { // Must have no special characters or whitespace String val = null; long l = dbl.longValue(); if (l > Integer.MAX_VALUE) { Long lo = new Long(dbl.longValue()); val = lo.toString().toUpperCase(); int suffix = val.indexOf("L"); if (suffix != -1) val = val.substring(0, suffix); } else { Integer i = new Integer(dbl.intValue()); val = i.toString(); } result = new BigInteger(val.trim()); } } else { result = null; } } else { DecoderFactory.invalidType(encodedObject, desiredClass); } return result; } }