blob: b8115999ce9342cb4456e399bd9d3761f8fccfc8 [file] [log] [blame]
/*
* 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 org.apache.daffodil.dpath
import java.lang.{ Boolean => JBoolean }
import java.lang.{ Byte => JByte }
import java.lang.{ Double => JDouble }
import java.lang.{ Float => JFloat }
import java.lang.{ Integer => JInt }
import java.lang.{ Long => JLong }
import java.lang.{ Short => JShort }
import java.math.{ BigDecimal => JBigDecimal }
import java.math.{ BigInteger => JBigInt }
import org.apache.daffodil.calendar.DFDLDate
import org.apache.daffodil.calendar.DFDLDateTime
import org.apache.daffodil.dpath.NodeInfo.PrimType
import org.apache.daffodil.infoset.DataValue.DataValueBigDecimal
import org.apache.daffodil.infoset.DataValue.DataValueBigInt
import org.apache.daffodil.infoset.DataValue.DataValueBool
import org.apache.daffodil.infoset.DataValue.DataValueByte
import org.apache.daffodil.infoset.DataValue.DataValueDate
import org.apache.daffodil.infoset.DataValue.DataValueDateTime
import org.apache.daffodil.infoset.DataValue.DataValueDouble
import org.apache.daffodil.infoset.DataValue.DataValueFloat
import org.apache.daffodil.infoset.DataValue.DataValueInt
import org.apache.daffodil.infoset.DataValue.DataValueLong
import org.apache.daffodil.infoset.DataValue.DataValuePrimitive
import org.apache.daffodil.infoset.DataValue.DataValueShort
import org.apache.daffodil.infoset.DataValue.DataValueString
import org.apache.daffodil.infoset.DataValue.DataValueTime
import org.apache.daffodil.util.Numbers.asBigInt
import org.apache.daffodil.util.Numbers.asBoolean
import org.apache.daffodil.util.Numbers.asDouble
case object BooleanToLong extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong =
JLong.valueOf(if (asBoolean(a.getAnyRef) == true) 1L else 0L)
}
case object BooleanToString extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueString =
if (asBoolean(a.getAnyRef) == true) "true" else "false"
}
case object DateTimeToDate extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDate = {
a.getAnyRef match {
case dt: DFDLDateTime => dt.toDate
case _ => throw new NumberFormatException("xs:dateTime expected but an invalid type was received.")
}
}
}
case object DateTimeToTime extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueTime = {
a.getAnyRef match {
case dt: DFDLDateTime => dt.toTime
case _ => throw new NumberFormatException("xs:dateTime expected but an invalid type was received.")
}
}
}
case object DateToDateTime extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDateTime = {
a.getAnyRef match {
case d: DFDLDate => d.toDateTime
case _ => throw new NumberFormatException("xs:date expected but an invalid type was received.")
}
}
}
case object DecimalToInteger extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt =
PrimType.Integer.fromNumber(a.getBigDecimal).getBigInt
}
case object DecimalToLong extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong =
PrimType.Long.fromNumber(a.getBigDecimal).getLong
}
case object DecimalToDouble extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble =
PrimType.Double.fromNumber(a.getBigDecimal).getDouble
}
case object DecimalToNonNegativeInteger extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt =
PrimType.NonNegativeInteger.fromNumber(a.getBigDecimal).getBigInt
}
case object DecimalToUnsignedLong extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt =
PrimType.UnsignedLong.fromNumber(a.getBigDecimal).getBigInt
}
case object DecimalToBoolean extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool = {
val d = a.getBigDecimal
val comp = d.compareTo(JBigDecimal.ZERO)
val b =
if (comp == 0) false
else true
asBoolean(b)
}
}
case object DoubleToDecimal extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigDecimal =
PrimType.Decimal.fromNumber(a.getDouble).getBigDecimal
}
case object DoubleToFloat extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueFloat =
PrimType.Float.fromNumber(a.getDouble).getFloat
}
case object DoubleToLong extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong =
PrimType.Long.fromNumber(a.getDouble).getLong
}
case object DoubleToUnsignedLong extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt =
asBigInt(PrimType.UnsignedLong.fromNumber(a.getDouble).getAnyRef)
}
case object DoubleToBoolean extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool = {
val d = a.getDouble
val b =
if (d == 0.0) false
else if (d.isNaN()) false
else true
asBoolean(b)
}
}
case object FloatToDouble extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble =
PrimType.Double.fromNumber(a.getFloat).getDouble
}
case object IntegerToDecimal extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigDecimal =
PrimType.Decimal.fromNumber(a.getBigInt).getBigDecimal
}
case object IntegerToUnsignedLong extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt =
PrimType.UnsignedLong.fromNumber(a.getBigInt).getBigInt
}
case object LongToBoolean extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool =
asBoolean(if (a.getLong == 0) false else true)
}
case object LongToByte extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueByte =
PrimType.Byte.fromNumber(a.getLong).getByte
}
case object LongToDecimal extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigDecimal =
PrimType.Decimal.fromNumber(a.getLong).getBigDecimal
}
case object LongToDouble extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble =
PrimType.Double.fromNumber(a.getLong).getDouble
}
case object LongToFloat extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueFloat =
PrimType.Float.fromNumber(a.getLong).getFloat
}
case object LongToInt extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueInt =
PrimType.Int.fromNumber(a.getLong).getInt
}
case object LongToInteger extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt =
PrimType.Integer.fromNumber(a.getLong).getBigInt
}
case object LongToShort extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueShort =
PrimType.Short.fromNumber(a.getLong).getShort
}
case object LongToArrayIndex extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong =
PrimType.Long.fromNumber(a.getLong).getLong
}
case object LongToUnsignedByte extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueShort =
PrimType.UnsignedByte.fromNumber(a.getLong).getShort
}
case object LongToUnsignedInt extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong =
PrimType.UnsignedInt.fromNumber(a.getLong).getLong
}
case object LongToUnsignedShort extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueInt =
PrimType.UnsignedShort.fromNumber(a.getLong).getInt
}
case object LongToNonNegativeInteger extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt =
PrimType.NonNegativeInteger.fromNumber(a.getLong).getBigInt
}
case object LongToUnsignedLong extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt =
PrimType.UnsignedLong.fromNumber(a.getLong).getBigInt
}
case object NumericToDouble extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble =
asDouble(a.getAnyRef)
}
case object StringToBoolean extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool =
PrimType.Boolean.fromXMLString(a.getString).getBoolean
}
case object StringToDecimal extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigDecimal =
PrimType.Decimal.fromXMLString(a.getString).getBigDecimal
}
case object StringToDouble extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueDouble =
PrimType.Double.fromXMLString(a.getString).getDouble
}
case object StringToLong extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueLong =
PrimType.Long.fromXMLString(a.getString).getLong
}
case object StringToUnsignedLong extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBigInt =
PrimType.UnsignedLong.fromXMLString(a.getString).getBigInt
}
/**
* Summary: Computes the effective boolean value of the sequence \$arg.
*
* If \$arg is the empty sequence, fn:boolean returns false.
*
* If \$arg is a sequence whose first item is a node, fn:boolean returns true.
*
* If \$arg is a singleton value of type xs:boolean or a derived from
* xs:boolean, fn:boolean returns \$arg.
*
* If \$arg is a singleton value of type xs:string or a type derived from
* xs:string, xs:anyURI or a type derived from xs:anyURI or xs:untypedAtomic,
* fn:boolean returns false if the operand value has zero length; otherwise
* it returns true.
*
* If \$arg is a singleton value of any numeric type or a type derived
* from a numeric type, fn:boolean returns false if the operand value
* is NaN or is numerically equal to zero; otherwise it returns true.
*
* In all other cases, fn:boolean raises a type error [err:FORG0006].
*/
case object FNToBoolean extends Converter {
override def computeValue(a: DataValuePrimitive, dstate: DState): DataValueBool = {
val res = a.getAnyRef match {
case b: JBoolean => b.booleanValue()
case s: String => if (s.length == 0) false else true
case d: JDouble => if (d.isNaN() || d == 0) false else true
case f: JFloat => if (f.isNaN() || f == 0) false else true
//
// BigDecimal does not have a representation for NaN or Infinite
case bd: JBigDecimal => if (bd.compareTo(JBigDecimal.ZERO) == 0) false else true
case b: JByte => if (b == 0) false else true
case s: JShort => if (s == 0) false else true
case i: JInt => if (i == 0) false else true
case l: JLong => if (l == 0) false else true
case bi: JBigInt => if (bi.compareTo(JBigInt.ZERO) == 0) false else true
// TODO: Once sequences are supported, fill in these case statements
//case s: LocalSequence if s.length == 0 => false
//case s: LocalSequence if s(0) == Node => true
case _ => throw new NumberFormatException("Invalid argument type.")
}
res
}
}