efinnegan closed pull request #83: Adding value of 'bcd' to binaryCalendarRep URL: https://github.com/apache/incubator-daffodil/pull/83
This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala index e83e40a50..17129af26 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala @@ -30,6 +30,15 @@ import org.apache.daffodil.dsom.ExpressionCompilers import org.apache.daffodil.dsom.InitiatedTerminatedMixin import org.apache.daffodil.exceptions.Assert import org.apache.daffodil.grammar.primitives.AlignmentFill +import org.apache.daffodil.grammar.primitives.BCDDateKnownLengthPrim +import org.apache.daffodil.grammar.primitives.BCDDateRuntimeLengthPrim +import org.apache.daffodil.grammar.primitives.BCDDateTimeKnownLengthPrim +import org.apache.daffodil.grammar.primitives.BCDDateTimeRuntimeLengthPrim +import org.apache.daffodil.grammar.primitives.BCDTimeKnownLengthPrim +import org.apache.daffodil.grammar.primitives.BCDTimeRuntimeLengthPrim +import org.apache.daffodil.grammar.primitives.BCDTimeDelimitedLengthPrim +import org.apache.daffodil.grammar.primitives.BCDDateTimeDelimitedLengthPrim +import org.apache.daffodil.grammar.primitives.BCDDateDelimitedLengthPrim import org.apache.daffodil.grammar.primitives.BCDDecimalDelimitedEndOfData import org.apache.daffodil.grammar.primitives.BCDDecimalKnownLength import org.apache.daffodil.grammar.primitives.BCDDecimalRuntimeLength @@ -130,6 +139,7 @@ import org.apache.daffodil.schema.annotation.props.NotFound import org.apache.daffodil.schema.annotation.props.gen.BinaryCalendarRep import org.apache.daffodil.schema.annotation.props.gen.BinaryFloatRep import org.apache.daffodil.schema.annotation.props.gen.BinaryNumberRep +import org.apache.daffodil.schema.annotation.props.gen.CalendarPatternKind import org.apache.daffodil.schema.annotation.props.gen.LengthKind import org.apache.daffodil.schema.annotation.props.gen.LengthUnits import org.apache.daffodil.schema.annotation.props.gen.NilKind @@ -496,8 +506,14 @@ trait ElementBaseGrammarMixin case LengthKind.Implicit => implicitBinaryLengthInBits case LengthKind.Explicit if (lengthEv.isConstant) => explicitBinaryLengthInBits() case LengthKind.Explicit => -1 // means must be computed at runtime. - case LengthKind.Delimited if (binaryNumberRep == BinaryNumberRep.Binary) => subsetError("lengthKind='delimited' only supported for packed binary formats.") - case LengthKind.Delimited => -1 // only for packed binary data, length must be computed at runtime. + case LengthKind.Delimited => primType match { + case PrimType.DateTime | PrimType.Date | PrimType.Time => + if (binaryCalendarRep == BinaryCalendarRep.BinaryMilliseconds || binaryCalendarRep == BinaryCalendarRep.BinarySeconds) + subsetError("lengthKind='delimited' only supported for packed binary formats.") + else -1 // only for packed binary data, length must be computed at runtime. + case _ => if (binaryNumberRep == BinaryNumberRep.Binary) subsetError("lengthKind='delimited' only supported for packed binary formats.") + else -1 // only for packed binary data, length must be computed at runtime. + } case LengthKind.Pattern => schemaDefinitionError("Binary data elements cannot have lengthKind='pattern'.") case LengthKind.Prefixed => subsetError("lengthKind='prefixed' not yet supported.") case LengthKind.EndOfParent => schemaDefinitionError("Binary data elements cannot have lengthKind='endOfParent'.") @@ -829,7 +845,26 @@ trait ElementBaseGrammarMixin case (_, n) => SDE("binary xs:dateTime must be 64 bits when binaryCalendarRep='binaryMilliseconds'. Length in bits was %s.", n) } case (_, BinaryCalendarRep.BinaryMilliseconds) => SDE("binaryCalendarRep='binaryMilliseconds' is not allowed with type %s", primType.name) - case _ => notYetImplemented("Type %s when representation='binary' and binaryCalendarRep=%s", primType.name, binaryCalendarRep.toString) + case (_, BinaryCalendarRep.Bcd) => { + if ((binaryNumberKnownLengthInBits != -1) && (binaryNumberKnownLengthInBits % 4) != 0) + SDE("The given length (%s bits) must be a multiple of 4 when using binaryCalendarRep='%s'.", binaryNumberKnownLengthInBits, binaryCalendarRep) + if (calendarPatternKind != CalendarPatternKind.Explicit) + SDE("calendarPatternKind must be 'explicit' when binaryCalendarRep='%s'", binaryCalendarRep) + + (primType, lengthKind, binaryNumberKnownLengthInBits) match { + case (PrimType.DateTime, LengthKind.Delimited, -1) => new BCDDateTimeDelimitedLengthPrim(this) + case (PrimType.DateTime, _, -1) => new BCDDateTimeRuntimeLengthPrim(this) + case (PrimType.DateTime, _, _) => new BCDDateTimeKnownLengthPrim(this, binaryNumberKnownLengthInBits) + case (PrimType.Date, LengthKind.Delimited, -1) => new BCDDateDelimitedLengthPrim(this) + case (PrimType.Date, _, -1) => new BCDDateRuntimeLengthPrim(this) + case (PrimType.Date, _, _) => new BCDDateKnownLengthPrim(this, binaryNumberKnownLengthInBits) + case (PrimType.Time, LengthKind.Delimited, -1) => new BCDTimeDelimitedLengthPrim(this) + case (PrimType.Time, _, -1) => new BCDTimeRuntimeLengthPrim(this) + case (PrimType.Time, _, _) => new BCDTimeKnownLengthPrim(this, binaryNumberKnownLengthInBits) + case _ => SDE("Invalid case.") + } + } + case _ => notYetImplemented("Type %s when representation='binary' and binaryCalendarRep=%s", primType.name, binaryCalendarRep.toString) } } diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesDateTime.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesDateTime.scala index e6f275e6e..235df44cb 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesDateTime.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesDateTime.scala @@ -23,16 +23,23 @@ import com.ibm.icu.util.Calendar import com.ibm.icu.util.TimeZone import com.ibm.icu.util.ULocale import org.apache.daffodil.dsom.ElementBase +import org.apache.daffodil.exceptions.Assert import org.apache.daffodil.grammar.Terminal import org.apache.daffodil.schema.annotation.props.gen.CalendarCheckPolicy import org.apache.daffodil.schema.annotation.props.gen.CalendarFirstDayOfWeek import org.apache.daffodil.schema.annotation.props.gen.CalendarPatternKind +import org.apache.daffodil.processors.unparsers.BinaryCalendarBCDRuntimeLengthUnparser +import org.apache.daffodil.processors.unparsers.BinaryCalendarBCDKnownLengthUnparser +import org.apache.daffodil.processors.unparsers.BinaryCalendarBCDDelimitedLengthUnparser import org.apache.daffodil.processors.unparsers.ConvertBinaryCalendarSecMilliUnparser import org.apache.daffodil.processors.unparsers.ConvertTextCalendarUnparser import com.ibm.icu.util.Calendar import com.ibm.icu.util.TimeZone import org.apache.daffodil.processors.CalendarEv import org.apache.daffodil.processors.CalendarLanguageEv +import org.apache.daffodil.processors.parsers.BinaryCalendarBCDDelimitedLengthParser +import org.apache.daffodil.processors.parsers.BinaryCalendarBCDKnownLengthParser +import org.apache.daffodil.processors.parsers.BinaryCalendarBCDRuntimeLengthParser import org.apache.daffodil.processors.parsers.ConvertBinaryCalendarSecMilliParser import org.apache.daffodil.processors.parsers.ConvertTextCalendarParser import org.apache.daffodil.processors.parsers.TextCalendarConstants @@ -47,32 +54,12 @@ abstract class ConvertCalendarPrimBase(e: ElementBase, guard: Boolean) override def toString = "to(xs:" + xsdType + ")" } -abstract class ConvertTextCalendarPrimBase(e: ElementBase, guard: Boolean) - extends ConvertCalendarPrimBase(e, guard) { +trait CalendarPrimBase { + def e: ElementBase protected def infosetPattern: String - protected def implicitPattern: String protected def validFormatCharacters: Seq[Char] - - lazy val pattern: String = { - val p = e.calendarPatternKind match { - case CalendarPatternKind.Explicit => e.calendarPattern - case CalendarPatternKind.Implicit => implicitPattern - } - - val escapedText = "(''|'[^']+'|[^a-zA-Z])".r - val patternNoEscapes = escapedText.replaceAllIn(p, "") - patternNoEscapes.toSeq.foreach(char => - if (!validFormatCharacters.contains(char)) { - SDE("Character '%s' not allowed in dfdl:calendarPattern for xs:%s".format(char, xsdType)) - }) - - if (patternNoEscapes.indexOf("S" * (TextCalendarConstants.maxFractionalSeconds + 1)) >= 0) { - SDE("More than %d fractional seconds unsupported in dfdl:calendarPattern for xs:%s".format(TextCalendarConstants.maxFractionalSeconds, xsdType)) - } - - p - } + protected def pattern: String val firstDay = e.calendarFirstDayOfWeek match { case CalendarFirstDayOfWeek.Sunday => Calendar.SUNDAY @@ -134,17 +121,44 @@ abstract class ConvertTextCalendarPrimBase(e: ElementBase, guard: Boolean) res } - private lazy val localeEv = { + protected lazy val localeEv = { val ev = new CalendarLanguageEv(e.calendarLanguage, e.erd) ev.compile() ev } - private lazy val calendarEv = { + protected lazy val calendarEv = { val cev = new CalendarEv(localeEv, calendarTz, firstDay, calendarDaysInFirstWeek, calendarCheckPolicy, e.erd) cev.compile() cev } +} + +abstract class ConvertTextCalendarPrimBase(e: ElementBase, guard: Boolean) + extends ConvertCalendarPrimBase(e, guard) + with CalendarPrimBase { + + protected def implicitPattern: String + + lazy val pattern: String = { + val p = e.calendarPatternKind match { + case CalendarPatternKind.Explicit => e.calendarPattern + case CalendarPatternKind.Implicit => implicitPattern + } + + val escapedText = "(''|'[^']+'|[^a-zA-Z])".r + val patternNoEscapes = escapedText.replaceAllIn(p, "") + patternNoEscapes.toSeq.foreach(char => + if (!validFormatCharacters.contains(char)) { + SDE("Character '%s' not allowed in dfdl:calendarPattern for xs:%s".format(char, xsdType)) + }) + + if (patternNoEscapes.indexOf("S" * (TextCalendarConstants.maxFractionalSeconds + 1)) >= 0) { + SDE("More than %d fractional seconds unsupported in dfdl:calendarPattern for xs:%s".format(TextCalendarConstants.maxFractionalSeconds, xsdType)) + } + + p + } override lazy val parser = new ConvertTextCalendarParser( e.elementRuntimeData, @@ -186,9 +200,27 @@ case class ConvertTextDateTimePrim(e: ElementBase) extends ConvertTextCalendarPr protected override val validFormatCharacters = "adDeEFGhHkKmMsSuwWvVyXxYzZ".toSeq } -abstract class ConvertBinaryCalendarPrimBase(e: ElementBase, guard: Boolean, lengthInBits: Long) - extends ConvertCalendarPrimBase(e, guard) { +abstract class BinaryPackedDecimalCalendarPrimBase(e: ElementBase, guard: Boolean) + extends ConvertCalendarPrimBase(e, guard) + with CalendarPrimBase { + lazy val pattern: String = { + val p = e.calendarPatternKind match { + case CalendarPatternKind.Explicit => e.calendarPattern + case _ => Assert.impossibleCase + } + + p.toSeq.foreach(char => + if (!validFormatCharacters.contains(char)) { + SDE("Character '%s' not allowed in dfdl:calendarPattern for xs:%s with a binaryCalendarRep of '%s'".format(char, xsdType, e.binaryCalendarRep)) + }) + + if (p.indexOf("S" * (TextCalendarConstants.maxFractionalSeconds + 1)) >= 0) { + SDE("More than %d fractional seconds unsupported in dfdl:calendarPattern for xs:%s".format(TextCalendarConstants.maxFractionalSeconds, xsdType)) + } + + p + } } case class ConvertBinaryDateTimeSecMilliPrim(e: ElementBase, lengthInBits: Long) extends ConvertCalendarPrimBase(e, true) { @@ -243,3 +275,155 @@ case class ConvertBinaryDateTimeSecMilliPrim(e: ElementBase, lengthInBits: Long) lengthInBits.toInt, !epochCalendar.getTimeZone.equals(TimeZone.UNKNOWN_ZONE)) } + +abstract class BCDRuntimeLength(e: ElementBase) extends BinaryPackedDecimalCalendarPrimBase(e, true) { + + override lazy val parser = new BinaryCalendarBCDRuntimeLengthParser( + e.elementRuntimeData, + false, + pattern, + localeEv, + calendarEv, + xsdType, + prettyType, + e.lengthEv, + e.lengthUnits) + + override lazy val unparser = + new BinaryCalendarBCDRuntimeLengthUnparser( + e.elementRuntimeData, + pattern, + localeEv, + calendarEv, + e.lengthEv, + e.lengthUnits) +} + +abstract class BCDKnownLength(e: ElementBase, lengthInBits: Long) extends BinaryPackedDecimalCalendarPrimBase(e, true) { + + override lazy val parser = new BinaryCalendarBCDKnownLengthParser( + e.elementRuntimeData, + false, + lengthInBits.toInt, + pattern, + localeEv, + calendarEv, + xsdType, + prettyType) + + override lazy val unparser = + new BinaryCalendarBCDKnownLengthUnparser( + e.elementRuntimeData, + lengthInBits.toInt, + pattern, + localeEv, + calendarEv) +} + +abstract class BCDDelimitedLength(e: ElementBase, xsdType: String, prettyType: String) + extends StringDelimited(e) + with CalendarPrimBase { + + lazy val pattern: String = { + val p = e.calendarPatternKind match { + case CalendarPatternKind.Explicit => e.calendarPattern + case _ => Assert.impossibleCase + } + + p.toSeq.foreach(char => + if (!validFormatCharacters.contains(char)) { + SDE("Character '%s' not allowed in dfdl:calendarPattern for xs:%s with a binaryCalendarRep of '%s'".format(char, xsdType, e.binaryCalendarRep)) + }) + + if (p.indexOf("S" * (TextCalendarConstants.maxFractionalSeconds + 1)) >= 0) { + SDE("More than %d fractional seconds unsupported in dfdl:calendarPattern for xs:%s".format(TextCalendarConstants.maxFractionalSeconds, xsdType)) + } + + p + } + + val isDelimRequired: Boolean = false + + override lazy val parser = new BinaryCalendarBCDDelimitedLengthParser( + e.elementRuntimeData, + false, + pattern, + localeEv, + calendarEv, + xsdType, + prettyType, + textDelimitedParser, + fieldDFAParseEv, + isDelimRequired) + + override lazy val unparser = + new BinaryCalendarBCDDelimitedLengthUnparser( + e.elementRuntimeData, + pattern, + localeEv, + calendarEv) + +} + +case class BCDDateKnownLengthPrim(e: ElementBase, lengthInBits: Long) + extends BCDKnownLength(e, lengthInBits) { + protected override val xsdType = "date" + protected override val prettyType = "Date" + protected override val infosetPattern = "uuuu-MM-ddxxx" + protected override val validFormatCharacters = "dDeEFGMuwWyXxYzZ".toSeq +} + +case class BCDDateRuntimeLengthPrim(e: ElementBase) extends BCDRuntimeLength(e) { + protected override val xsdType = "date" + protected override val prettyType = "Date" + protected override val infosetPattern = "uuuu-MM-ddxxx" + protected override val validFormatCharacters = "dDeEFGMuwWyXxYzZ".toSeq +} + +case class BCDDateDelimitedLengthPrim(e: ElementBase) + extends BCDDelimitedLength(e, "date", "Date") { + protected override val infosetPattern = "uuuu-MM-ddxxx" + protected override val validFormatCharacters = "dDeEFGMuwWyXxYzZ".toSeq +} + +case class BCDTimeKnownLengthPrim(e: ElementBase, lengthInBits: Long) + extends BCDKnownLength(e, lengthInBits) { + protected override val xsdType = "time" + protected override val prettyType = "Time" + protected override val infosetPattern = "HH:mm:ss.SSSSSSxxx" + protected override val validFormatCharacters = "ahHkKmsSvVzXxZ".toSeq +} + +case class BCDTimeRuntimeLengthPrim(e: ElementBase) extends BCDRuntimeLength(e) { + protected override val xsdType = "time" + protected override val prettyType = "Time" + protected override val infosetPattern = "HH:mm:ss.SSSSSSxxx" + protected override val validFormatCharacters = "ahHkKmsSvVzXxZ".toSeq +} + +case class BCDTimeDelimitedLengthPrim(e: ElementBase) + extends BCDDelimitedLength(e, "time", "Time") { + protected override val infosetPattern = "HH:mm:ss.SSSSSSxxx" + protected override val validFormatCharacters = "ahHkKmsSvVzXxZ".toSeq +} + +case class BCDDateTimeKnownLengthPrim(e: ElementBase, lengthInBits: Long) + extends BCDKnownLength(e, lengthInBits) { + protected override val xsdType = "dateTime" + protected override val prettyType = "DateTime" + protected override val infosetPattern = "uuuu-MM-dd'T'HH:mm:ss.SSSSSSxxx" + protected override val validFormatCharacters = "adDeEFGhHkKmMsSuwWvVyXxYzZ".toSeq +} + +case class BCDDateTimeRuntimeLengthPrim(e: ElementBase) extends BCDRuntimeLength(e) { + protected override val xsdType = "dateTime" + protected override val prettyType = "DateTime" + protected override val infosetPattern = "uuuu-MM-dd'T'HH:mm:ss.SSSSSSxxx" + protected override val validFormatCharacters = "adDeEFGhHkKmMsSuwWvVyXxYzZ".toSeq +} + +case class BCDDateTimeDelimitedLengthPrim(e: ElementBase) + extends BCDDelimitedLength(e, "dateTime", "DateTime") { + protected override val infosetPattern = "uuuu-MM-dd'T'HH:mm:ss.SSSSSSxxx" + protected override val validFormatCharacters = "adDeEFGhHkKmMsSuwWvVyXxYzZ".toSeq +} diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertBinaryCalendarUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertBinaryCalendarUnparser.scala index f948c2286..397739162 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertBinaryCalendarUnparser.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertBinaryCalendarUnparser.scala @@ -17,16 +17,29 @@ package org.apache.daffodil.processors.unparsers +import java.lang.{ Long => JLong } +import java.math.{ BigDecimal => JBigDecimal } +import java.math.{ BigInteger => JBigInteger } + import org.apache.daffodil.calendar.DFDLCalendar import org.apache.daffodil.exceptions.Assert import org.apache.daffodil.io.DataOutputStream import org.apache.daffodil.io.FormatInfo +import org.apache.daffodil.processors.CalendarEv +import org.apache.daffodil.processors.CalendarLanguageEv import org.apache.daffodil.processors.ElementRuntimeData +import org.apache.daffodil.processors.Evaluatable +import org.apache.daffodil.processors.parsers.ConvertTextCalendarProcessorBase +import org.apache.daffodil.processors.parsers.HasKnownLengthInBits +import org.apache.daffodil.processors.parsers.HasRuntimeExplicitLength import org.apache.daffodil.schema.annotation.props.gen.BinaryCalendarRep +import org.apache.daffodil.schema.annotation.props.gen.LengthUnits +import org.apache.daffodil.util.DecimalUtils import org.apache.daffodil.util.Maybe.One import org.apache.daffodil.util.Misc import com.ibm.icu.util.Calendar +import com.ibm.icu.util.ULocale case class ConvertBinaryCalendarSecMilliUnparser( override val context: ElementRuntimeData, @@ -51,7 +64,7 @@ case class ConvertBinaryCalendarSecMilliUnparser( val calValue = node.dataValue match { case dc: DFDLCalendar => dc.calendar - case x => Assert.invariantFailed("ConvertTextCalendar received unsupported type. %s of type %s.".format(x, Misc.getNameFromClass(x))) + case x => Assert.invariantFailed("ConvertBinaryCalendar received unsupported type. %s of type %s.".format(x, Misc.getNameFromClass(x))) } // Adjust the time based on time zone - if a time zone wasn't specified, Calendar will assume the default @@ -82,3 +95,110 @@ case class ConvertBinaryCalendarSecMilliUnparser( } } } + +abstract class BinaryCalendarBCDUnparser ( + override val context: ElementRuntimeData, + pattern: String, + localeEv: CalendarLanguageEv, + calendarEv: CalendarEv) + extends ConvertTextCalendarProcessorBase { + + protected def fromBigInteger(bigInt: JBigInteger, nBits: Int): Array[Byte] = DecimalUtils.bcdFromBigInteger(bigInt, nBits) + + protected def putNumber(dos: DataOutputStream, bigDec: JBigDecimal, nBits: Int, finfo: FormatInfo): Boolean = { + val packedNum = fromBigInteger(bigDec.unscaledValue, nBits) + dos.putByteArray(packedNum, packedNum.length * 8, finfo) + } + + def doUnparse(state: UState, bitLength: Int): Unit = { + + val locale: ULocale = localeEv.evaluate(state) + val calendar: Calendar = calendarEv.evaluate(state) + + calendar.clear() + + val df = tlDataFormatter(locale, calendar) + df.setCalendar(calendar) + + val node = state.currentInfosetNode.asSimple + + val calValue = node.dataValue match { + case dc: DFDLCalendar => dc.calendar + case x => Assert.invariantFailed("ConvertBinaryCalendar received unsupported type. %s of type %s.".format(x, Misc.getNameFromClass(x))) + } + + val str: String = df.format(calValue) + + val strAsBigDec: JBigDecimal = DecimalUtils.bcdToBigDecimal(DecimalUtils.bcdFromBigInteger(new JBigInteger(str), 0), 0) + + val dos = state.dataOutputStream + val res = putNumber(dos, strAsBigDec, bitLength, state) + + if (!res) { + Assert.invariant(dos.maybeRelBitLimit0b.isDefined) + UnparseError(One(state.schemaFileLocation), One(state.currentLocation), "Insufficient space to unparse element %s, required %s bits, but only %s were available.", + context.dpathElementCompileInfo.namedQName.toPrettyString, bitLength, dos.maybeRelBitLimit0b.get) + } + } +} + +case class BinaryCalendarBCDKnownLengthUnparser( + override val context: ElementRuntimeData, + lengthInBits: Int, + pattern: String, + localeEv: CalendarLanguageEv, + calendarEv: CalendarEv) + extends BinaryCalendarBCDUnparser(context, pattern, localeEv, calendarEv) + with PrimUnparser + with HasKnownLengthInBits { + + /** + * Primitive unparsers must override runtimeDependencies + */ + override lazy val runtimeDependencies = Seq(localeEv, calendarEv) + + def unparse(state: UState): Unit = { + doUnparse(state, lengthInBits) + } +} + +case class BinaryCalendarBCDRuntimeLengthUnparser( + override val e: ElementRuntimeData, + pattern: String, + localeEv: CalendarLanguageEv, + calendarEv: CalendarEv, + val lengthEv: Evaluatable[JLong], + val lUnits: LengthUnits) + extends BinaryCalendarBCDUnparser(e, pattern, localeEv, calendarEv) + with PrimUnparser + with HasRuntimeExplicitLength { + + /** + * Primitive unparsers must override runtimeDependencies + */ + override lazy val runtimeDependencies = Seq(localeEv, calendarEv, lengthEv) + + def unparse(state: UState): Unit = { + doUnparse(state, getBitLength(state)) + } + +} + +case class BinaryCalendarBCDDelimitedLengthUnparser( + val e: ElementRuntimeData, + pattern: String, + localeEv: CalendarLanguageEv, + calendarEv: CalendarEv) + extends BinaryCalendarBCDUnparser(e, pattern, localeEv, calendarEv) + with PrimUnparser { + + /** + * Primitive unparsers must override runtimeDependencies + */ + override lazy val runtimeDependencies = Seq(localeEv, calendarEv) + + def unparse(state: UState): Unit = { + doUnparse(state, 0) + } + +} diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextCalendarUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextCalendarUnparser.scala index 16d25f204..77bdd3211 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextCalendarUnparser.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertTextCalendarUnparser.scala @@ -28,11 +28,11 @@ import org.apache.daffodil.processors.ElementRuntimeData import org.apache.daffodil.util.Misc import org.apache.daffodil.processors.parsers.ConvertTextCalendarProcessorBase -case class ConvertTextCalendarUnparser(erd: ElementRuntimeData, +case class ConvertTextCalendarUnparser(context: ElementRuntimeData, pattern: String, localeEv: CalendarLanguageEv, calendarEv: CalendarEv) - extends ConvertTextCalendarProcessorBase(erd, pattern) + extends ConvertTextCalendarProcessorBase with TextPrimUnparser { /** diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/PackedBinaryTraits.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/PackedBinaryTraits.scala index 040dbadc3..14fa43ede 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/PackedBinaryTraits.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/PackedBinaryTraits.scala @@ -169,7 +169,7 @@ abstract class PackedBinaryDecimalDelimitedBaseParser( } else { try { val num = toBigDecimal(fieldBytes, binaryDecimalVirtualPoint) - state.simpleElement.setDataValue(num) + writeResult(state, num) } catch { case n: NumberFormatException => PE(state, "Error in packed data: \n%s", n.getMessage()) } @@ -179,4 +179,8 @@ abstract class PackedBinaryDecimalDelimitedBaseParser( return } } + + def writeResult(state: PState, num: BigDecimal) { + state.simpleElement.setDataValue(num) + } } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PrimitivesDateTime1.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PrimitivesDateTime1.scala index 7ff6b7dee..bcb0bd1e2 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PrimitivesDateTime1.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PrimitivesDateTime1.scala @@ -17,23 +17,34 @@ package org.apache.daffodil.processors.parsers +import java.lang.{ Long => JLong } +import java.math.{ BigDecimal => JBigDecimal, BigInteger => JBigInteger } import java.text.ParsePosition import com.ibm.icu.text.SimpleDateFormat import com.ibm.icu.util.Calendar import com.ibm.icu.util.ULocale import org.apache.daffodil.exceptions.Assert + import org.apache.daffodil.calendar.DFDLDateTime import org.apache.daffodil.calendar.DFDLTime import org.apache.daffodil.calendar.DFDLDate import org.apache.daffodil.processors.CalendarEv import org.apache.daffodil.processors.CalendarLanguageEv import org.apache.daffodil.processors.ElementRuntimeData +import org.apache.daffodil.processors.Evaluatable +import org.apache.daffodil.processors.FieldDFAParseEv +import org.apache.daffodil.processors.ParseOrUnparseState import org.apache.daffodil.processors.Processor +import org.apache.daffodil.processors.dfa.TextDelimitedParserBase import org.apache.daffodil.schema.annotation.props.gen.BinaryCalendarRep +import org.apache.daffodil.schema.annotation.props.gen.LengthUnits +import org.apache.daffodil.util.DecimalUtils + +trait ConvertTextCalendarProcessorBase extends Processor { + + override val context: ElementRuntimeData + val pattern: String -abstract class ConvertTextCalendarProcessorBase( - override val context: ElementRuntimeData, - pattern: String) extends Processor { // The dfdl:calendarLanguage property can be a runtime-valued expression. // Hence, locale and calendar, derived from it, can also be runtime-valued. // @@ -82,26 +93,15 @@ abstract class ConvertTextCalendarProcessorBase( } } -case class ConvertTextCalendarParser(erd: ElementRuntimeData, - xsdType: String, - prettyType: String, - pattern: String, - hasTZ: Boolean, - localeEv: CalendarLanguageEv, - calendarEv: CalendarEv) - extends ConvertTextCalendarProcessorBase(erd, pattern) - with TextPrimParser { - - override lazy val runtimeDependencies = List(localeEv, calendarEv) - - def parse(start: PState): Unit = { - val node = start.simpleElement - val str = node.dataValueAsString - - Assert.invariant(str != null) +trait CalendarParser extends PrimParser with ConvertTextCalendarProcessorBase { + def localeEv: CalendarLanguageEv + def calendarEv: CalendarEv + def xsdType: String + def prettyType: String + def hasTZ: Boolean + def writeResult (start: PState, toWrite: String) { val pos = new ParsePosition(0) - val locale: ULocale = localeEv.evaluate(start) val calendar: Calendar = calendarEv.evaluate(start) @@ -114,13 +114,14 @@ case class ConvertTextCalendarParser(erd: ElementRuntimeData, val df = tlDataFormatter(locale, calendar) val cal = df.getCalendar.clone.asInstanceOf[Calendar] - df.parse(str, cal, pos); + + df.parse(toWrite, cal, pos); // Verify that what was parsed was what was passed exactly in byte count // Use pos to verify all characters consumed & check for errors - if (pos.getIndex != str.length || pos.getErrorIndex >= 0) { + if (pos.getIndex != toWrite.length || pos.getErrorIndex >= 0) { val errIndex = if (pos.getErrorIndex >= 0) pos.getErrorIndex else pos.getIndex - PE(start, "Convert to %s (for xs:%s): Failed to parse '%s' at character %d.", prettyType, xsdType, str, errIndex + 1) + PE(start, "Convert to %s (for xs:%s): Failed to parse '%s' at character %d.", prettyType, xsdType, toWrite, errIndex + 1) return } @@ -132,7 +133,7 @@ case class ConvertTextCalendarParser(erd: ElementRuntimeData, cal.getTime } catch { case e: IllegalArgumentException => { - PE(start, "Convert to %s (for xs:%s): Failed to parse '%s': %s.", prettyType, xsdType, str, e.getMessage()) + PE(start, "Convert to %s (for xs:%s): Failed to parse '%s': %s.", prettyType, xsdType, toWrite, e.getMessage()) return } } @@ -144,8 +145,28 @@ case class ConvertTextCalendarParser(erd: ElementRuntimeData, case _ => Assert.impossibleCase } - node.overwriteDataValue(newCal) + start.simpleElement.overwriteDataValue(newCal) + } +} + +case class ConvertTextCalendarParser(context: ElementRuntimeData, + xsdType: String, + prettyType: String, + pattern: String, + hasTZ: Boolean, + localeEv: CalendarLanguageEv, + calendarEv: CalendarEv) + extends CalendarParser + with TextPrimParser { + + override lazy val runtimeDependencies = List(localeEv, calendarEv) + def parse(start: PState): Unit = { + val node = start.simpleElement + val str = node.dataValueAsString + + Assert.invariant(str != null) + writeResult(start, str) } } @@ -180,6 +201,8 @@ case class ConvertBinaryCalendarSecMilliParser( override lazy val runtimeDependencies = Nil + def toBigDecimal(num: Array[Byte], scale: Int): JBigDecimal = DecimalUtils.bcdToBigDecimal(num, scale) + def parse(start: PState): Unit = { val dis = start.dataInputStream @@ -207,3 +230,94 @@ case class ConvertBinaryCalendarSecMilliParser( start.simpleElement.overwriteDataValue(newCal) } } + +abstract class BinaryCalendarBCDParser( + override val context: ElementRuntimeData, + hasTZ: Boolean, + pattern: String, + localeEv: CalendarLanguageEv, + calendarEv: CalendarEv, + xsdType: String, + prettyType: String) + extends CalendarParser { + + def toBigDecimal(num: Array[Byte], scale: Int): JBigDecimal = DecimalUtils.bcdToBigDecimal(num, scale) + + def getBitLength(start: ParseOrUnparseState): Int + + def parse(start: PState): Unit = { + + val dis = start.dataInputStream + val nBits = getBitLength(start) + if (nBits == 0) return // zero length is used for outputValueCalc often. + + if (!dis.isDefinedForLength(nBits)) { + PE(start, "Insufficient bits in data. Needed %d bit(s) but found only %d available.", nBits, dis.remainingBits.get) + return + } + + try { + // Use '0' for the binaryDecimalVirtualPoint because its location will be implied by the pattern + val bigDec: BigDecimal = toBigDecimal(dis.getByteArray(nBits, start), 0) + writeResult(start, bigDec.toString()) + } catch { + case n: NumberFormatException => PE(start, "Error in packed data: \n%s", n.getMessage()) + } + } +} + +case class BinaryCalendarBCDKnownLengthParser( + override val context: ElementRuntimeData, + hasTZ: Boolean, + lengthInBits: Int, + pattern: String, + localeEv: CalendarLanguageEv, + calendarEv: CalendarEv, + xsdType: String, + prettyType: String) + extends BinaryCalendarBCDParser(context, hasTZ, pattern, localeEv, calendarEv, xsdType, prettyType) + with PrimParser + with HasKnownLengthInBits { + + override lazy val runtimeDependencies = List(localeEv, calendarEv) +} + +case class BinaryCalendarBCDRuntimeLengthParser( + override val e: ElementRuntimeData, + hasTZ: Boolean, + pattern: String, + localeEv: CalendarLanguageEv, + calendarEv: CalendarEv, + xsdType: String, + prettyType: String, + val lengthEv: Evaluatable[JLong], + val lUnits: LengthUnits) + extends BinaryCalendarBCDParser(e, hasTZ, pattern, localeEv, calendarEv, xsdType, prettyType) + with PrimParser + with HasRuntimeExplicitLength { + + override lazy val runtimeDependencies = List(localeEv, calendarEv, lengthEv) +} + +case class BinaryCalendarBCDDelimitedLengthParser( + e: ElementRuntimeData, + hasTZ: Boolean, + pattern: String, + localeEv: CalendarLanguageEv, + calendarEv: CalendarEv, + xsdType: String, + prettyType: String, + textParser: TextDelimitedParserBase, + fieldDFAEv: FieldDFAParseEv, + isDelimRequired: Boolean) + extends PackedBinaryDecimalDelimitedBaseParser(e, textParser, fieldDFAEv, isDelimRequired, 0 ) + with CalendarParser { + + override def toBigInteger(num: Array[Byte]): JBigInteger = DecimalUtils.bcdToBigInteger(num) + def toBigDecimal(num: Array[Byte], scale: Int): JBigDecimal = DecimalUtils.bcdToBigDecimal(num, scale) + + override def writeResult(state: PState, num: BigDecimal) { + super[CalendarParser].writeResult(state, num.toString()) + } + +} diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml index 8d215cd75..f413ee867 100644 --- a/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml +++ b/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml @@ -263,9 +263,62 @@ dfdl:binaryCalendarRep="binarySeconds" dfdl:binaryCalendarEpoch="2000-1-1T00:00"/> <xs:element name="dateTimeBin11" type="xs:dateTime" dfdl:lengthKind="implicit" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="binarySeconds" dfdl:binaryCalendarEpoch="01-01-2000T00:00:00"/> + <xs:element name="dateTimeBin12" type="xs:dateTime" dfdl:lengthKind="delimited" dfdl:terminator=";" + dfdl:binaryCalendarRep="binarySeconds" dfdl:binaryCalendarEpoch="1977-01-01T00:00:07"/> + + <xs:element name="dateBinBCD" type="xs:date" dfdl:calendarPattern="MMddyy" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="explicit" dfdl:length="{ 3 }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd"/> + <xs:element name="dateBinBCD2" type="xs:date" dfdl:calendarPattern="MMddyyyy" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="explicit" dfdl:length="{ 4 }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd"/> + <xs:element name="dateBinBCD3" type="xs:date" dfdl:calendarPattern="MM-dd-yy" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="explicit" dfdl:length="{ 3 }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd"/> + <xs:element name="dateBinBCD4" type="xs:date" dfdl:calendarPattern="MMddyy" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="explicit" dfdl:length="{ 7 }" dfdl:lengthUnits="bits" dfdl:binaryCalendarRep="bcd"/> + + <xs:element name="timeBinBCD" type="xs:time" dfdl:calendarPattern="HHmmss" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="explicit" dfdl:length="{ 3 }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd"/> + <xs:element name="timeBinBCD2" type="xs:time" dfdl:calendarPattern="HHmmssSSSS" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="explicit" dfdl:length="{ 5 }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd"/> + <xs:element name="timeBinBCD3" type="xs:time" dfdl:calendarPatternKind="implicit" + dfdl:lengthKind="explicit" dfdl:length="{ 5 }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd"/> + <xs:element name="timeBinBCD4" type="xs:time" dfdl:calendarPattern="HHmmss" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="implicit" dfdl:binaryCalendarRep="bcd"/> + <xs:element name="timeBinBCD5" type="xs:time" dfdl:calendarPattern="HHmmss" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="delimited" dfdl:terminator=";" dfdl:binaryCalendarRep="bcd" dfdl:encoding="ISO-8859-1"/> + + <xs:element name="timeBinBCD6"> + <xs:complexType> + <xs:sequence> + <xs:element name="length" type="xs:int" dfdl:representation="binary" + dfdl:lengthKind="explicit" dfdl:length="{ 1 }" dfdl:lengthUnits="bytes" /> + <xs:element name="time" type="xs:time" dfdl:calendarPattern="HHmmss" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="explicit" dfdl:length="{ ../ex:length }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd" /> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:element name="dateTimeBinBCD" type="xs:dateTime" dfdl:calendarPattern="MMddyyyyHHmmss" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="explicit" dfdl:length="{ 7 }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd"/> + <xs:element name="dateTimeBinBCD2" type="xs:dateTime" dfdl:calendarPattern="MMddyyyyhhmmss" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="implicit" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd"/> + <xs:element name="dateTimeBinBCD3" type="xs:dateTime" dfdl:calendarPattern="MMddyyyyhhmmss" dfdl:calendarPatternKind="explicit" + dfdl:lengthKind="explicit" dfdl:length="{ 7 }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="bcd"/> + + <xs:element name="dateTimeBinBCD4"> + <xs:complexType> + <xs:sequence> + <xs:element name="num1" type="xs:decimal" dfdl:encoding="ISO-8859-1" dfdl:representation="binary" dfdl:binaryNumberRep="bcd" + dfdl:lengthKind="delimited" dfdl:terminator=";" dfdl:binaryDecimalVirtualPoint="0"/> + <xs:element name="datetime" type="xs:dateTime" dfdl:calendarPattern="MMddyyyyHHmmss" dfdl:encoding="ISO-8859-1" + dfdl:calendarPatternKind="explicit" dfdl:binaryCalendarRep="bcd" dfdl:lengthKind="delimited" dfdl:terminator=";"/> + <xs:element name="num2" type="xs:decimal" dfdl:encoding="ISO-8859-1" dfdl:representation="binary" dfdl:binaryNumberRep="bcd" + dfdl:lengthKind="delimited" dfdl:terminator=";" dfdl:binaryDecimalVirtualPoint="0"/> + </xs:sequence> + </xs:complexType> + </xs:element> - <xs:element name="dateBin2" type="xs:date" dfdl:lengthKind="explicit" dfdl:length="{ 4 }" - dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="binarySeconds" dfdl:binaryCalendarEpoch="1970-01-01T00:00:00+00:00"/> + <xs:element name="dateBinInvalid" type="xs:date" dfdl:calendarPattern="yyyy.MM.dd" dfdl:calendarPatternKind="explicit" dfdl:lengthKind="explicit" + dfdl:length="{ 4 }" dfdl:lengthUnits="bytes" dfdl:binaryCalendarRep="binarySeconds" dfdl:binaryCalendarEpoch="1970-01-01T00:00:00+00:00"/> </tdml:defineSchema> @@ -2251,7 +2304,244 @@ </tdml:errors> </tdml:parserTestCase> - <tdml:parserTestCase name="dateBin2" root="dateBin2" + <tdml:parserTestCase name="dateTimeBin20" root="dateTimeBin12" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="false"> + + <tdml:document> + <tdml:documentPart type="bits">00000000 00000000 00000000 00111101</tdml:documentPart> + </tdml:document> + <tdml:errors> + <tdml:error>Schema Definition Error: Subset lengthKind='delimited' only supported for packed binary formats.</tdml:error> + </tdml:errors> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateBinBCD" root="dateBinBCD" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="byte">12 14 23</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <dateBinBCD>2023-12-14</dateBinBCD> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateBinBCD2" root="dateBinBCD2" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="byte">12 14 20 23</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <dateBinBCD2>2023-12-14</dateBinBCD2> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateBinBCD3" root="dateBinBCD" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="false"> + + <tdml:document> + <tdml:documentPart type="byte">12 0F 23</tdml:documentPart> + </tdml:document> + <tdml:errors> + <tdml:error>Parse Error</tdml:error> + <tdml:error>Invalid low nibble</tdml:error> + </tdml:errors> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateBinBCD4" root="dateBinBCD3" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="false"> + + <tdml:document> + <tdml:documentPart type="byte">08 17 48</tdml:documentPart> + </tdml:document> + <tdml:errors> + <tdml:error>Schema Definition Error</tdml:error> + <tdml:error>Character '-' not allowed in dfdl:calendarPattern for xs:date with a binaryCalendarRep of 'bcd'</tdml:error> + </tdml:errors> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateBinBCD5" root="dateBinBCD4" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="false"> + + <tdml:document> + <tdml:documentPart type="bits">0000000</tdml:documentPart> + </tdml:document> + <tdml:errors> + <tdml:error>Schema Definition Error</tdml:error> + <tdml:error>The given length (7 bits) must be a multiple of 4 when using binaryCalendarRep='bcd'</tdml:error> + </tdml:errors> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateBinBCD6" root="dateBinBCD" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="bits">0001 0010 0010 0111 1001 1001</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <dateBinBCD>1999-12-27</dateBinBCD> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="timeBinBCD" root="timeBinBCD" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="byte">18 56 03</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <timeBinBCD>18:56:03.000000</timeBinBCD> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="timeBinBCD2" root="timeBinBCD2" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="twoPass"> + + <tdml:document> + <tdml:documentPart type="byte">01 45 00 99 87</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <timeBinBCD2>01:45:00.998000</timeBinBCD2> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="timeBinBCD3" root="timeBinBCD3" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="false"> + + <tdml:document> + <tdml:documentPart type="byte">01 45 00 99 87</tdml:documentPart> + </tdml:document> + <tdml:errors> + <tdml:error>Schema Definition Error</tdml:error> + <tdml:error>calendarPatternKind must be 'explicit' when binaryCalendarRep='bcd'</tdml:error> + </tdml:errors> + </tdml:parserTestCase> + + <tdml:parserTestCase name="timeBinBCD4" root="timeBinBCD4" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="byte">18 56 03</tdml:documentPart> + </tdml:document> + <tdml:errors> + <tdml:error>Schema Definition Error</tdml:error> + <tdml:error>Size of binary data 'Time' cannot be determined implicitly</tdml:error> + </tdml:errors> + </tdml:parserTestCase> + + <tdml:parserTestCase name="timeBinBCD5" root="timeBinBCD5" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="byte">18 56 03 3B</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <timeBinBCD5>18:56:03.000000</timeBinBCD5> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="timeBinBCD6" root="timeBinBCD6" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="byte">03 18 56 03</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <timeBinBCD6> + <length>3</length> + <time>18:56:03.000000</time> + </timeBinBCD6> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateTimeBinBCD" root="dateTimeBinBCD" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="byte">06 14 20 04 18 56 03</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <dateTimeBinBCD>2004-06-14T18:56:03.000000</dateTimeBinBCD> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateTimeBinBCD2" root="dateTimeBinBCD2" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="false"> + + <tdml:document> + <tdml:documentPart type="byte">01 45 00 99 87</tdml:documentPart> + </tdml:document> + <tdml:errors> + <tdml:error>Schema Definition Error</tdml:error> + <tdml:error>Size of binary data 'DateTime' with binaryCalendarRep='bcd' cannot be determined implicitly</tdml:error> + </tdml:errors> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateTimeBinBCD3" root="dateTimeBinBCD3" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="byte">06 14 20 04 18 56 03</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <dateTimeBinBCD3>2004-06-14T18:56:03.000000</dateTimeBinBCD3> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateTimeBinBCD4" root="dateTimeBinBCD4" + model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" + roundTrip="true"> + + <tdml:document> + <tdml:documentPart type="byte">03 3B 06 14 20 04 18 56 03 3B 19 3B</tdml:documentPart> + </tdml:document> + <tdml:infoset> + <tdml:dfdlInfoset> + <dateTimeBinBCD4> + <num1>3</num1> + <datetime>2004-06-14T18:56:03.000000</datetime> + <num2>19</num2> + </dateTimeBinBCD4> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <tdml:parserTestCase name="dateBinInvalid" root="dateBinInvalid" model="SimpleTypes-binary" description="Section 5 Schema types-dateTime - DFDL-5-016R" roundTrip="false"> diff --git a/daffodil-test/src/test/scala-debug/org/apache/daffodil/section05/simple_types/TestSimpleTypesDebug.scala b/daffodil-test/src/test/scala-debug/org/apache/daffodil/section05/simple_types/TestSimpleTypesDebug.scala index a2498e1eb..499a13d9d 100644 --- a/daffodil-test/src/test/scala-debug/org/apache/daffodil/section05/simple_types/TestSimpleTypesDebug.scala +++ b/daffodil-test/src/test/scala-debug/org/apache/daffodil/section05/simple_types/TestSimpleTypesDebug.scala @@ -117,4 +117,6 @@ class TestSimpleTypesDebug { // DAFFODIL-1946 @Test def test_dateTimeImplicitPatternFail5() { runner.runOneTest("dateTimeImplicitPatternFail5") } + + @Test def test_dateTimeBinBCD3() { runner.runOneTest("dateTimeBinBCD3") } } diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala index a87831393..1957606b9 100644 --- a/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala +++ b/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala @@ -189,7 +189,24 @@ class TestSimpleTypes { @Test def test_dateTimeBin17() { runner.runOneTest("dateTimeBin17") } @Test def test_dateTimeBin18() { runner.runOneTest("dateTimeBin18") } @Test def test_dateTimeBin19() { runner.runOneTest("dateTimeBin19") } - @Test def test_dateBin2() { runner.runOneTest("dateBin2") } + @Test def test_dateTimeBin20() { runner.runOneTest("dateTimeBin20") } + @Test def test_dateBinBCD() { runner.runOneTest("dateBinBCD") } + @Test def test_dateBinBCD2() { runner.runOneTest("dateBinBCD2") } + @Test def test_dateBinBCD3() { runner.runOneTest("dateBinBCD3") } + @Test def test_dateBinBCD4() { runner.runOneTest("dateBinBCD4") } + @Test def test_dateBinBCD5() { runner.runOneTest("dateBinBCD5") } + @Test def test_dateBinBCD6() { runner.runOneTest("dateBinBCD6") } + @Test def test_timeBinBCD() { runner.runOneTest("timeBinBCD") } + @Test def test_timeBinBCD2() { runner.runOneTest("timeBinBCD2") } + @Test def test_timeBinBCD3() { runner.runOneTest("timeBinBCD3") } + @Test def test_timeBinBCD4() { runner.runOneTest("timeBinBCD4") } + @Test def test_timeBinBCD5() { runner.runOneTest("timeBinBCD5") } + @Test def test_timeBinBCD6() { runner.runOneTest("timeBinBCD6") } + @Test def test_dateTimeBinBCD() { runner.runOneTest("dateTimeBinBCD") } + @Test def test_dateTimeBinBCD2() { runner.runOneTest("dateTimeBinBCD2") } + //@Test def test_dateTimeBinBCD3() { runner.runOneTest("dateTimeBinBCD3") } + @Test def test_dateTimeBinBCD4() { runner.runOneTest("dateTimeBinBCD4") } + @Test def test_dateBinInvalid() { runner.runOneTest("dateBinInvalid") } @Test def test_dateTimeImplicitPattern() { runner.runOneTest("dateTimeImplicitPattern") } @Test def test_dateTimeImplicitPatternFail() { runner.runOneTest("dateTimeImplicitPatternFail") } ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services