/* * Copyright (C) 2000 - 2014 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://openbd.org/ * $Id: cfNumberData.java 2429 2014-03-30 19:44:57Z alan $ */ package com.naryx.tagfusion.cfm.engine; import com.nary.util.NumberUtils; import com.nary.util.string; import com.naryx.tagfusion.cfm.parser.CFContext; /** * The cfNumberData class represents numbers in tagServlet. */ public class cfNumberData extends cfJavaObjectData { static final long serialVersionUID = 1; private double doubleNo; private int intNo; private boolean bIntNo = false; private boolean modified = false; private boolean isJavaNumeric = false; private String image; private transient cfDateData dateData; /** * In all instances of the constructor a call to super("") is made. * This is because the returned String from a call to getClass().getName() * on a cfNumber has to return "java.lang.String". */ public cfNumberData( double _data ) { this( _data, null ); } public cfNumberData( double _data, String _image ) { super( string.EMPTY_STRING ); doubleNo = _data; bIntNo = false; image = _image; } /* * When the float constructor was added, long values would call it instead of the * double constructor causing the value to be truncated. This constructor was added * to force a long to be cast to a double. */ public cfNumberData( long _data ) { super( string.EMPTY_STRING ); doubleNo = _data; bIntNo = false; this.image = String.valueOf( _data ); } public cfNumberData( Long _data ) { super( _data ); isJavaNumeric = true; doubleNo = _data.longValue(); bIntNo = false; this.image = String.valueOf( _data ); } /* * This constructor causes a float to be more accurately coerced to a double. */ public cfNumberData( Float _data ) { super( _data ); isJavaNumeric = true; doubleNo = ( new Double( String.valueOf( _data.floatValue() ) ) ).doubleValue(); bIntNo = false; } public cfNumberData( Double _data ) { super( _data ); isJavaNumeric = true; doubleNo = _data.doubleValue(); bIntNo = false; } public cfNumberData( Integer _data ) { super( _data ); isJavaNumeric = true; intNo = _data.intValue(); bIntNo = true; } public cfNumberData( Short _data ) { super( _data ); isJavaNumeric = true; intNo = _data.shortValue(); bIntNo = true; } public cfNumberData( int _data ) { this( _data, null ); } public cfNumberData( int _data, String _image ) { super( string.EMPTY_STRING ); intNo = _data; bIntNo = true; image = _image; } public cfNumberData( cfNumberData _data ) { super( string.EMPTY_STRING ); bIntNo = _data.bIntNo; intNo = _data.intNo; doubleNo = _data.doubleNo; instance = _data.instance; } public byte getDataType() { return cfData.CFNUMBERDATA; } public String getName() { return getString(); } public String getDataTypeName() { return "number"; } public boolean isInt() { return bIntNo; } public boolean isJavaNumeric() { return isJavaNumeric; } public void add( int inc ) { set( intNo + inc ); } public void add( double inc ) { set( doubleNo + inc ); } public boolean isBooleanConvertible() { return true; } public boolean getBoolean() { if ( ( bIntNo && intNo == 0 ) || ( !bIntNo && doubleNo == 0 ) ) return false; else return true; } public boolean isDateConvertible() { return true; } public cfDateData getDateData() { if ( dateData == null ) { dateData = cfDateData.createDateFromDays( getDouble() ); } return dateData; } public long getDateLong() { return ( long ) ( ( bIntNo ? intNo : doubleNo ) * 86400000 ); } public boolean isNumberConvertible() { return true; } public double getDouble() { return ( bIntNo ? ( double )intNo : doubleNo ); } public long getLong() { return ( bIntNo ? ( long )intNo : ( long )doubleNo ); } public int getInt() { return ( bIntNo ? intNo : ( int )doubleNo ); } public void set( int _newValue ) { intNo = _newValue; bIntNo = true; modified = true; dateData = null; image = null; } public void set( double _newValue ) { doubleNo = _newValue; bIntNo = false; modified = true; dateData = null; image = null; } public cfData duplicate() { if ( bIntNo ) return new cfNumberData( intNo, image ); else return new cfNumberData( doubleNo, image ); } public String getString() { if ( image != null ) { return image; } else if ( bIntNo ) { return String.valueOf( intNo ); } else { return NumberUtils.getString( doubleNo ); } } public cfNumberData getNumber() { return this; } public static cfNumberData getNumber( Number _n ) { return new cfNumberData( _n.doubleValue() ); } public static cfNumberData getNumber( Long _l ) { return new cfNumberData( _l.intValue() ); } public static cfNumberData getNumber( Float _f ) { return new cfNumberData( _f.doubleValue() ); } // this version of equals() is for use by the CFML expression engine public boolean equals( cfData _data ) throws cfmRunTimeException { if ( _data.getDataType() == cfData.CFNUMBERDATA ) { cfNumberData d2 = ( cfNumberData )_data; if ( d2.isInt() ) { return d2.getInt() == ( bIntNo ? intNo : doubleNo ); } else { return d2.getDouble() == ( bIntNo ? intNo : doubleNo ); } } else if ( _data.getDataType() == cfData.CFSTRINGDATA ) { return getString().equals( _data.getString() ); } else { return super.equals( _data ); // throw an exception } } // this version of equals() is for use by generic Collections classes public boolean equals( Object o ) { if ( o instanceof cfNumberData ) { cfNumberData d2 = ( cfNumberData )o; if ( d2.isInt() ) { return d2.getInt() == ( bIntNo ? intNo : doubleNo ); } else { return d2.getDouble() == ( bIntNo ? intNo : doubleNo ); } } else if ( o instanceof cfStringData ) { return getString().equals( ( ( cfStringData )o ).getString() ); } return false; } public int hashCode() { return ( bIntNo ? new Integer( intNo ).hashCode() : new Double( doubleNo ).hashCode() ); } /** * The following methods override their corresponding methods from cfJavaObjectData * allowing for the instance attribute to be updated prior to the call. * This means that the instance field is only being updated when a Java method * is called which is highly unlikely. */ public cfData getJavaData( javaMethodDataInterface _method, CFContext _context ) throws cfmRunTimeException { if ( modified || instance == null || instance.equals( string.EMPTY_STRING ) ) instance = bIntNo ? ( String.valueOf( intNo ) ) : ( String.valueOf( doubleNo ) ); return super.getJavaData( _method, _context ); } public cfData getJavaData( String _methodOrField ) throws cfmRunTimeException { if ( modified || instance == null || instance.equals( string.EMPTY_STRING ) ) instance = bIntNo ? ( String.valueOf( intNo ) ) : ( String.valueOf( doubleNo ) ); return super.getJavaData( _methodOrField ); } public cfData getJavaData( cfData _Field ) throws cfmRunTimeException { if ( modified || instance == null || instance.equals( string.EMPTY_STRING ) ) instance = bIntNo ? ( String.valueOf( intNo ) ) : ( String.valueOf( doubleNo ) ); return super.getJavaData( _Field ); } public void dump( java.io.PrintWriter out, String _label, int _top ) { out.print( this.getString() ); } public String toString() { return getString(); } public void dumpWDDX( int version, java.io.PrintWriter out ) { if ( version > 10 ) { out.write( "<n>" ); out.write( getString() ); out.write( "</n>" ); } else { out.write( "<number>" ); out.write( getString() ); out.write( "</number>" ); } } public Class<?> getInstanceClass() { // in the instance where this cfNumberData is precompiled then the instanceClass will be null // therefore we need to check if it is, and if so return String.class (note that isJavaNumeric // will be false invariably in this case hence String.class can safely be returned) Class<?> instCls = super.getInstanceClass(); if ( instCls == null ) return String.class; else return instCls; } }