mbeckerle commented on a change in pull request #643: URL: https://github.com/apache/daffodil/pull/643#discussion_r716108602
########## File path: daffodil-test/src/test/resources/org/apache/daffodil/layers/checkDigit.dfdl.xsd ########## @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> + + +<schema xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" + xmlns:dfdlx="http://www.ogf.org/dfdl/dfdl-1.0/extensions" + xmlns:fn="http://www.w3.org/2005/xpath-functions" + xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" + xmlns:cd="urn:org.apache.daffodil.layers.checkDigit" + xmlns:ex="http://example.com" + xmlns:tns="http://example.com" + targetNamespace="http://example.com"> + + <include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" /> + + <import + namespace="urn:org.apache.daffodil.layers.checkDigit" + schemaLocation="org/apache/daffodil/layers/xsd/checkDigitLayer.dfdl.xsd"/> + + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:format ref="tns:GeneralFormat" encoding="ascii" /> + </appinfo> + </annotation> + + <element name="r"> + <complexType> + <sequence> + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:newVariableInstance ref="cd:checkDigit"/> + </appinfo> + </annotation> + <sequence> + <sequence dfdl:ref="cd:checkDigitExplicit" dfdlx:layerLength="10"> + <element name="value" type="tns:dateType"/> + </sequence> + <element name="checkDigit" type="tns:u1" dfdl:initiator=":" + dfdl:outputValueCalc='{ $cd:checkDigit }'/> + <element name="computedCheckDigit" type="tns:u1" + dfdl:inputValueCalc='{ $cd:checkDigit }'/> + <sequence> + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:assert + failureType="recoverableError" + test='{ checkDigit eq $cd:checkDigit }' + message='{ fn:concat("Incorrect check digit: ", checkDigit, ". Should be: ", $cd:checkDigit, ".") }' /> + </appinfo> + </annotation> + </sequence> + </sequence> + </sequence> + </complexType> + </element> + + <simpleType name="dateType" + dfdl:lengthKind="explicit" + dfdl:length="10" + dfdl:calendarPatternKind="explicit" + dfdl:calendarPattern="yyyy-MM-dd"> + <restriction base="xs:date"/> + </simpleType> + + <simpleType name="u5" dfdl:length="5"> + <restriction base="tns:fixedInt"/> + </simpleType> + + <simpleType name="u1" dfdl:length="1"> + <restriction base="tns:fixedInt"/> + </simpleType> + + <simpleType name="fixedInt" dfdl:lengthKind="explicit" Review comment: remove unused type ########## File path: daffodil-test/src/test/scala/org/apache/daffodil/layers/IPv4Checksum.scala ########## @@ -0,0 +1,239 @@ +/* + * 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.layers + +import org.apache.commons.io.IOUtils +import org.apache.daffodil.schema.annotation.props.gen.LayerLengthKind +import org.apache.daffodil.schema.annotation.props.gen.LayerLengthUnits +import org.apache.daffodil.util.Maybe +import org.apache.daffodil.processors.LayerLengthEv +import org.apache.daffodil.processors.LayerBoundaryMarkEv +import org.apache.daffodil.processors.LayerCharsetEv +import org.apache.daffodil.processors.parsers.PState +import org.apache.daffodil.processors.unparsers.UState + +import java.io._ +import org.apache.daffodil.dpath.NodeInfo.PrimType +import org.apache.daffodil.exceptions.Assert +import org.apache.daffodil.io.DataInputStream +import org.apache.daffodil.processors.SequenceRuntimeData +import org.apache.daffodil.processors.SuspendableOperation +import org.apache.daffodil.util.ByteBufferOutputStream +import org.apache.daffodil.util.Maybe.One +import org.apache.daffodil.xml.NS +import org.apache.daffodil.xml.RefQName +import passera.unsigned.UShort + +import java.nio.ByteBuffer +import java.nio.ShortBuffer + +/** + * The layer transform computes the checksum of the header data. + * per IETF RFC 791. + * + * The data has a well-known fixed length, so layerLengthKind is always 'implicit'. + */ +final class IPv4Checksum(srd: SequenceRuntimeData) +extends LayerTransformer() { + + private def hdrLengthInBytes = 20 + + private def chksumShortIndex = 5 + + private val finalChecksumVRD = { + val varNamespace = NS("urn:org.apache.daffodil.layers.IPv4Checksum") + val finalChecksumVarQName = RefQName(Some("chksum"), "IPv4Checksum", varNamespace).toGlobalQName + val vrd = srd.variableMap.getVariableRuntimeData(finalChecksumVarQName).getOrElse { + srd.SDE("Variable '%s' is not defined.", finalChecksumVarQName.toExtendedSyntax) + } + srd.schemaDefinitionUnless(vrd.primType == PrimType.UnsignedShort, + "Variable '%s' is not of type 'xs:unsignedShort'.", finalChecksumVarQName.toExtendedSyntax) + vrd + } + + /** + * The header data will be captured here. All the limiting streams and + * the byte/short buffers are all aliases into this same object. + */ + private val hdrByteArr = new Array[Byte](hdrLengthInBytes) + + /** + * Stream from which the header will be parsed. + */ + private val limitingInputStream = new ByteArrayInputStream(hdrByteArr) + + + /** + * ByteBuffer view of the header bytes. + */ + private val byteBuf = ByteBuffer.wrap(hdrByteArr) // bigEndian byte order by default + private val shortBuf = byteBuf.asShortBuffer() + + /** + * Stream to which the header will be unparsed. + */ + private val limitingOutputStream = new ByteBufferOutputStream(byteBuf) + + /** + * Assigned by wrapLimitingStream for parsing to capture the original source + * of the header bytes for parsing. + */ + private var optOriginalInputStream: Maybe[InputStream] = Maybe.Nope + + /** + * Assigned by wrapLimitingStream for unparsing to capture the original + * output stream to which the bytes are ultimately written. + */ + private var optOriginalOutputStream: Maybe[OutputStream] = Maybe.Nope + + protected def wrapLayerDecoder(jis: InputStream) = jis + + protected def wrapLimitingStream(jis: InputStream, state: PState) = { + optOriginalInputStream = One(jis) + limitingInputStream + } + + protected def wrapLayerEncoder(jos: OutputStream) = jos + + protected def wrapLimitingStream(jos: OutputStream, state: UState) = { + optOriginalOutputStream = One(jos) + limitingOutputStream + } + + /** + * Shared by both parsing and unparsing. Contains the checksum algorithm. + */ + private def computeChecksum(shortBuf: ShortBuffer): Int = { + var i = 0 + var chksum: Int = 0 + val nShorts = hdrLengthInBytes / 2 + while (i < nShorts) { + if (i == chksumShortIndex) { + // for the checksum calculation treat the incoming checksum field of the data as 0 + // so we just don't do an addition here. + } else { + chksum += UShort(shortBuf.get(i)).toInt + } + Assert.invariant(chksum >= 0) + i += 1 + } + // + // now combine the carry bits in the most significant 16 bits into the lower 16 bits. + // + val checksumLow = chksum & 0xFFFF + val checksumHigh = chksum >>> 16 + val checksumTotal: Int = checksumLow + checksumHigh + Assert.invariant(checksumTotal <= 0xFFFF && checksumTotal >= 0) + val checksumTotalShort = UShort(checksumTotal.toShort) + val checksum = checksumTotalShort.toInt + // + // take ones complement to get the final checksum + // + val finalChecksum: Int = (~checksum) & 0xFFFF + finalChecksum + } + + override def startLayerForParse(s: PState): Unit = { + // + // For parsing, all the hard work happens here, allowing the layered input stream to + // just deliver the bytes + // + Assert.invariant(s.bitPos0b % 8 == 0) // we are byte aligned. + Assert.invariant(optOriginalInputStream.isDefined) + val bitLen = hdrLengthInBytes * 8 + + try + IOUtils.readFully(optOriginalInputStream.get, hdrByteArr) + catch { + case eof: EOFException => + throw DataInputStream.NotEnoughDataException(bitLen) Review comment: Need test that exercises this case. Need to throw specific (thin throwable) exception here that is caught in layer parser to convert to a PE. ########## File path: daffodil-test/src/test/scala/org/apache/daffodil/layers/CheckDigit.scala ########## @@ -0,0 +1,205 @@ +/* + * 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.layers + +import org.apache.commons.io.IOUtils +import org.apache.daffodil.schema.annotation.props.gen.LayerLengthKind +import org.apache.daffodil.schema.annotation.props.gen.LayerLengthUnits +import org.apache.daffodil.util.Maybe +import org.apache.daffodil.processors.LayerLengthEv +import org.apache.daffodil.processors.LayerBoundaryMarkEv +import org.apache.daffodil.processors.LayerCharsetEv +import org.apache.daffodil.processors.parsers.PState +import org.apache.daffodil.processors.unparsers.UState + +import java.io._ +import org.apache.daffodil.dpath.NodeInfo.PrimType +import org.apache.daffodil.exceptions.Assert +import org.apache.daffodil.io.DataInputStream +import org.apache.daffodil.processors.CharsetEvBase +import org.apache.daffodil.processors.SequenceRuntimeData +import org.apache.daffodil.processors.SuspendableOperation +import org.apache.daffodil.processors.charset.BitsCharsetJava +import org.apache.daffodil.util.ByteBufferOutputStream +import org.apache.daffodil.xml.NS +import org.apache.daffodil.xml.RefQName + +import java.nio.ByteBuffer +import java.nio.charset.Charset + + +final class CheckDigitExplicit( + srd: SequenceRuntimeData, + charset: Charset, + layerLengthEv: LayerLengthEv) +extends LayerTransformer() { + Assert.invariant(charset.newDecoder().maxCharsPerByte() == 1) // is a SBCS charset + + private val checkDigitVRD = { + val varNamespace = NS("urn:org.apache.daffodil.layers.checkDigit") + val varQName = RefQName(Some("cd"), "checkDigit", varNamespace).toGlobalQName + val vrd = srd.variableMap.getVariableRuntimeData(varQName).getOrElse { + srd.SDE("Variable '%s' is not defined.", varQName.toExtendedSyntax) + } + srd.schemaDefinitionUnless(vrd.primType == PrimType.UnsignedInt, + "Variable '%s' is not of type 'xs:unsignedInt'.", varQName.toExtendedSyntax) + vrd + } + + private var limitingOutputStream : ByteBufferOutputStream = _ + private var originalOutputStream: OutputStream = _ + + protected def wrapLayerDecoder(jis: InputStream) = jis + + override def wrapLimitingStream(jis: java.io.InputStream, state: PState) = { + val layerLengthInBytes: Int = layerLengthEv.evaluate(state).toInt + val ba = new Array[Byte](layerLengthInBytes) + try + IOUtils.readFully(jis, ba) + catch { + case eof: EOFException => + throw DataInputStream.NotEnoughDataException(ba.length * 8) + } + // this stream will be used by the parse when it parses the + // schema contents of the layer. We have already consumed the bytes + // from the original input stream, and saved those in the byte array + // to enable the computation of the checkDigit. + val layerStream = new ByteArrayInputStream(ba) + val str = new String(ba, charset) // always does replacement on decode errors. + val checkDigit = computeCheckDigit(str) + state.setVariable(checkDigitVRD, checkDigit, srd) // assign to result variable + layerStream + } + + protected def wrapLayerEncoder(jos: OutputStream) = jos + + protected def wrapLimitingStream(jos: OutputStream, state: UState) = { + originalOutputStream = jos + val layerLengthInBytes: Int = layerLengthEv.evaluate(state).toInt + val ba = new Array[Byte](layerLengthInBytes) + val byteBuf = ByteBuffer.wrap(ba) // bigEndian byte order by default Review comment: Fix comment. We're not using byte order in this example. ########## File path: daffodil-test/src/test/resources/org/apache/daffodil/layers/xsd/checkDigitLayer.dfdl.xsd ########## @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<schema + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:fn="http://www.w3.org/2005/xpath-functions" + xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" + xmlns:dfdlx="http://www.ogf.org/dfdl/dfdl-1.0/extensions" + xmlns:cd="urn:org.apache.daffodil.layers.checkDigit" + targetNamespace="urn:org.apache.daffodil.layers.checkDigit" + elementFormDefault="unqualified"> + + <include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" /> + + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + + <dfdl:format ref="cd:GeneralFormat" /> + + <dfdl:defineVariable name="checkDigit" type="xs:unsignedInt"/> + Review comment: move checkDigitType to here. Add facets for min 0 max 9. ########## File path: daffodil-test/src/test/scala/org/apache/daffodil/layers/CheckDigit.scala ########## @@ -0,0 +1,205 @@ +/* + * 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.layers + +import org.apache.commons.io.IOUtils +import org.apache.daffodil.schema.annotation.props.gen.LayerLengthKind +import org.apache.daffodil.schema.annotation.props.gen.LayerLengthUnits +import org.apache.daffodil.util.Maybe +import org.apache.daffodil.processors.LayerLengthEv +import org.apache.daffodil.processors.LayerBoundaryMarkEv +import org.apache.daffodil.processors.LayerCharsetEv +import org.apache.daffodil.processors.parsers.PState +import org.apache.daffodil.processors.unparsers.UState + +import java.io._ +import org.apache.daffodil.dpath.NodeInfo.PrimType +import org.apache.daffodil.exceptions.Assert +import org.apache.daffodil.io.DataInputStream +import org.apache.daffodil.processors.CharsetEvBase +import org.apache.daffodil.processors.SequenceRuntimeData +import org.apache.daffodil.processors.SuspendableOperation +import org.apache.daffodil.processors.charset.BitsCharsetJava +import org.apache.daffodil.util.ByteBufferOutputStream +import org.apache.daffodil.xml.NS +import org.apache.daffodil.xml.RefQName + +import java.nio.ByteBuffer +import java.nio.charset.Charset + + +final class CheckDigitExplicit( + srd: SequenceRuntimeData, + charset: Charset, + layerLengthEv: LayerLengthEv) +extends LayerTransformer() { + Assert.invariant(charset.newDecoder().maxCharsPerByte() == 1) // is a SBCS charset + + private val checkDigitVRD = { + val varNamespace = NS("urn:org.apache.daffodil.layers.checkDigit") + val varQName = RefQName(Some("cd"), "checkDigit", varNamespace).toGlobalQName + val vrd = srd.variableMap.getVariableRuntimeData(varQName).getOrElse { + srd.SDE("Variable '%s' is not defined.", varQName.toExtendedSyntax) + } + srd.schemaDefinitionUnless(vrd.primType == PrimType.UnsignedInt, + "Variable '%s' is not of type 'xs:unsignedInt'.", varQName.toExtendedSyntax) + vrd + } + + private var limitingOutputStream : ByteBufferOutputStream = _ + private var originalOutputStream: OutputStream = _ + + protected def wrapLayerDecoder(jis: InputStream) = jis + + override def wrapLimitingStream(jis: java.io.InputStream, state: PState) = { + val layerLengthInBytes: Int = layerLengthEv.evaluate(state).toInt + val ba = new Array[Byte](layerLengthInBytes) + try + IOUtils.readFully(jis, ba) + catch { + case eof: EOFException => + throw DataInputStream.NotEnoughDataException(ba.length * 8) + } + // this stream will be used by the parse when it parses the + // schema contents of the layer. We have already consumed the bytes + // from the original input stream, and saved those in the byte array + // to enable the computation of the checkDigit. + val layerStream = new ByteArrayInputStream(ba) + val str = new String(ba, charset) // always does replacement on decode errors. + val checkDigit = computeCheckDigit(str) + state.setVariable(checkDigitVRD, checkDigit, srd) // assign to result variable + layerStream + } + + protected def wrapLayerEncoder(jos: OutputStream) = jos + + protected def wrapLimitingStream(jos: OutputStream, state: UState) = { + originalOutputStream = jos + val layerLengthInBytes: Int = layerLengthEv.evaluate(state).toInt + val ba = new Array[Byte](layerLengthInBytes) + val byteBuf = ByteBuffer.wrap(ba) // bigEndian byte order by default + limitingOutputStream = new ByteBufferOutputStream(byteBuf) + limitingOutputStream + } + + /** + * Shared by both parsing and unparsing. + * + * Ignores any non-digit character in the argument. + * + * The checkDigit is the total of all digits, viewed as a string, the last digit of that total. + */ + private def computeCheckDigit(s: String): Long = { Review comment: Explain why this is returning a Long. Because a Long is the type expected to be the representation of unsignedInt which is the variable type. ########## File path: daffodil-test/src/test/scala/org/apache/daffodil/layers/CheckDigit.scala ########## @@ -0,0 +1,205 @@ +/* + * 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.layers + +import org.apache.commons.io.IOUtils +import org.apache.daffodil.schema.annotation.props.gen.LayerLengthKind +import org.apache.daffodil.schema.annotation.props.gen.LayerLengthUnits +import org.apache.daffodil.util.Maybe +import org.apache.daffodil.processors.LayerLengthEv +import org.apache.daffodil.processors.LayerBoundaryMarkEv +import org.apache.daffodil.processors.LayerCharsetEv +import org.apache.daffodil.processors.parsers.PState +import org.apache.daffodil.processors.unparsers.UState + +import java.io._ +import org.apache.daffodil.dpath.NodeInfo.PrimType +import org.apache.daffodil.exceptions.Assert +import org.apache.daffodil.io.DataInputStream +import org.apache.daffodil.processors.CharsetEvBase +import org.apache.daffodil.processors.SequenceRuntimeData +import org.apache.daffodil.processors.SuspendableOperation +import org.apache.daffodil.processors.charset.BitsCharsetJava +import org.apache.daffodil.util.ByteBufferOutputStream +import org.apache.daffodil.xml.NS +import org.apache.daffodil.xml.RefQName + +import java.nio.ByteBuffer +import java.nio.charset.Charset + + +final class CheckDigitExplicit( + srd: SequenceRuntimeData, + charset: Charset, + layerLengthEv: LayerLengthEv) +extends LayerTransformer() { + Assert.invariant(charset.newDecoder().maxCharsPerByte() == 1) // is a SBCS charset + + private val checkDigitVRD = { + val varNamespace = NS("urn:org.apache.daffodil.layers.checkDigit") + val varQName = RefQName(Some("cd"), "checkDigit", varNamespace).toGlobalQName + val vrd = srd.variableMap.getVariableRuntimeData(varQName).getOrElse { + srd.SDE("Variable '%s' is not defined.", varQName.toExtendedSyntax) + } + srd.schemaDefinitionUnless(vrd.primType == PrimType.UnsignedInt, + "Variable '%s' is not of type 'xs:unsignedInt'.", varQName.toExtendedSyntax) + vrd + } + + private var limitingOutputStream : ByteBufferOutputStream = _ + private var originalOutputStream: OutputStream = _ + + protected def wrapLayerDecoder(jis: InputStream) = jis + + override def wrapLimitingStream(jis: java.io.InputStream, state: PState) = { + val layerLengthInBytes: Int = layerLengthEv.evaluate(state).toInt + val ba = new Array[Byte](layerLengthInBytes) + try + IOUtils.readFully(jis, ba) + catch { + case eof: EOFException => + throw DataInputStream.NotEnoughDataException(ba.length * 8) Review comment: Need test that exercises this error condition. Also need to catch this somewhere, or more likely throw a specific exception LayerNotEnoughDataException that can be caught in the layer parser to cause a parse error. ########## File path: daffodil-test/src/test/resources/org/apache/daffodil/layers/checkDigit.dfdl.xsd ########## @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> + + +<schema xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" + xmlns:dfdlx="http://www.ogf.org/dfdl/dfdl-1.0/extensions" + xmlns:fn="http://www.w3.org/2005/xpath-functions" + xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" + xmlns:cd="urn:org.apache.daffodil.layers.checkDigit" + xmlns:ex="http://example.com" + xmlns:tns="http://example.com" + targetNamespace="http://example.com"> + + <include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" /> + + <import + namespace="urn:org.apache.daffodil.layers.checkDigit" + schemaLocation="org/apache/daffodil/layers/xsd/checkDigitLayer.dfdl.xsd"/> + + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:format ref="tns:GeneralFormat" encoding="ascii" /> + </appinfo> + </annotation> + + <element name="r"> + <complexType> + <sequence> + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:newVariableInstance ref="cd:checkDigit"/> + </appinfo> + </annotation> + <sequence> + <sequence dfdl:ref="cd:checkDigitExplicit" dfdlx:layerLength="10"> + <element name="value" type="tns:dateType"/> + </sequence> + <element name="checkDigit" type="tns:u1" dfdl:initiator=":" + dfdl:outputValueCalc='{ $cd:checkDigit }'/> + <element name="computedCheckDigit" type="tns:u1" + dfdl:inputValueCalc='{ $cd:checkDigit }'/> + <sequence> + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:assert + failureType="recoverableError" + test='{ checkDigit eq $cd:checkDigit }' + message='{ fn:concat("Incorrect check digit: ", checkDigit, ". Should be: ", $cd:checkDigit, ".") }' /> + </appinfo> + </annotation> + </sequence> + </sequence> + </sequence> + </complexType> + </element> + + <simpleType name="dateType" + dfdl:lengthKind="explicit" + dfdl:length="10" + dfdl:calendarPatternKind="explicit" + dfdl:calendarPattern="yyyy-MM-dd"> + <restriction base="xs:date"/> + </simpleType> + + <simpleType name="u5" dfdl:length="5"> Review comment: remove unused type ########## File path: daffodil-test/src/test/resources/org/apache/daffodil/layers/checkDigit.dfdl.xsd ########## @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> + + +<schema xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" + xmlns:dfdlx="http://www.ogf.org/dfdl/dfdl-1.0/extensions" + xmlns:fn="http://www.w3.org/2005/xpath-functions" + xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" + xmlns:cd="urn:org.apache.daffodil.layers.checkDigit" + xmlns:ex="http://example.com" + xmlns:tns="http://example.com" + targetNamespace="http://example.com"> + + <include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" /> + + <import + namespace="urn:org.apache.daffodil.layers.checkDigit" + schemaLocation="org/apache/daffodil/layers/xsd/checkDigitLayer.dfdl.xsd"/> + + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:format ref="tns:GeneralFormat" encoding="ascii" /> + </appinfo> + </annotation> + + <element name="r"> + <complexType> + <sequence> + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:newVariableInstance ref="cd:checkDigit"/> + </appinfo> + </annotation> + <sequence> + <sequence dfdl:ref="cd:checkDigitExplicit" dfdlx:layerLength="10"> + <element name="value" type="tns:dateType"/> + </sequence> + <element name="checkDigit" type="tns:u1" dfdl:initiator=":" + dfdl:outputValueCalc='{ $cd:checkDigit }'/> + <element name="computedCheckDigit" type="tns:u1" + dfdl:inputValueCalc='{ $cd:checkDigit }'/> + <sequence> + <annotation> + <appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:assert + failureType="recoverableError" + test='{ checkDigit eq $cd:checkDigit }' + message='{ fn:concat("Incorrect check digit: ", checkDigit, ". Should be: ", $cd:checkDigit, ".") }' /> + </appinfo> + </annotation> + </sequence> + </sequence> + </sequence> + </complexType> + </element> + + <simpleType name="dateType" + dfdl:lengthKind="explicit" + dfdl:length="10" + dfdl:calendarPatternKind="explicit" + dfdl:calendarPattern="yyyy-MM-dd"> + <restriction base="xs:date"/> + </simpleType> + + <simpleType name="u5" dfdl:length="5"> + <restriction base="tns:fixedInt"/> + </simpleType> + + <simpleType name="u1" dfdl:length="1"> Review comment: change to checkDigitType and move to other xsd file. Add facets for min 0 max 9. change base to just unsignedInt. Consider changing type to xs:int so that code can use type Int. (not type Long) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
