protected def unparse()

in daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/UnseparatedSequenceUnparsers.scala [83:208]


  protected def unparse(state: UState): Unit = {

    state.groupIndexStack.push(1L) // one-based indexing

    var index = 0
    var doUnparser = false
    val limit = childUnparsers.length
    while (index < limit) {
      val childUnparser = childUnparsers(index)
      val trd = childUnparser.trd
      state.pushTRD(trd) // because we inspect before we invoke the unparser

      //
      // Unparsing an ordered sequence depends on the incoming
      // stream of infoset events matching up with the order that
      // they are expected as the unparser recurses through the
      // child term unparsers.
      //
      childUnparser match {
        case unparser: RepeatingChildUnparser => {
          state.arrayIterationIndexStack.push(1L)
          state.occursIndexStack.push(1L)
          val erd = unparser.erd
          var numOccurrences = 0
          val maxReps = unparser.maxRepeats(state)

          //
          // The number of occurrances we unparse is always exactly driven
          // by the number of infoset events for the repeating/optional element.
          //
          // For RepUnparser - array/optional case - in all cases we should get a
          // startArray event. If we don't then
          // the element must be entirely optional, so we get no events for it
          // at all.

          // we must have an event
          Assert.invariant(state.inspect, "No event for unparing.")

          val ev = state.inspectAccessor
          if (ev.erd eq erd) {
            // must be a start event for this array/optional unparser
            val isArr = ev.isArray
            Assert.invariant(ev.isStart && (isArr || ev.erd.isOptional))

            //
            // StartArray for this unparser's array element
            //
            unparser.startArrayOrOptional(state)
            while ({
              doUnparser = unparser.shouldDoUnparser(unparser, state)
              doUnparser
            }) {
              if (isArr)
                if (state.dataProc.isDefined)
                  state.dataProc.get.beforeRepetition(state, this)

              unparseOne(unparser, erd, state)
              numOccurrences += 1
              state.moveOverOneArrayIterationIndexOnly()
              state.moveOverOneOccursIndexOnly()
              state.moveOverOneGroupIndexOnly() // array elements are always represented.

              if (isArr)
                if (state.dataProc.isDefined)
                  state.dataProc.get.afterRepetition(state, this)
            }

            // DAFFODIL-115: if the number of occurrences is less than minOccurs we are supposed
            // to check if the element is defaultable and add elements until we reach that
            // number. Daffodil does not currently support defaulting during unparsing.

            unparser.checkFinalOccursCountBetweenMinAndMaxOccurs(
              state,
              unparser,
              numOccurrences,
              maxReps,
              state.arrayIterationPos - 1
            )
            unparser.endArrayOrOptional(erd, state)
          } else {
            // this is either a start event for a following element or an end event for a
            // parent element. Either way, we never saw a start event for this array/optional,
            // which means there were zero occurrenes. Make sure that is allowed for this array
            //
            // DAFFODIL-115: if the number of occurrences is less than minOccurs we are supposed
            // to check if the element is defaultable and add elements until we reach that
            // number. Daffodil does not currently support defaulting during unparsing.
            unparser.checkFinalOccursCountBetweenMinAndMaxOccurs(
              state,
              unparser,
              numOccurrences,
              maxReps,
              0
            )
          }

          state.arrayIterationIndexStack.pop()
          state.occursIndexStack.pop()
        }
        //
        case scalarUnparser => {
          unparseOne(scalarUnparser, trd, state)
          // only move over in group if the scalar "thing" is an element
          // that is represented.
          scalarUnparser.trd match {
            case erd: ElementRuntimeData if (!erd.isRepresented) => // ok, skip group advance
            case _ => state.moveOverOneGroupIndexOnly()
          }
        }
      }

      state.popTRD(trd)
      index += 1
      //
      // Note: the invariant is that unparsers move over 1 within their group themselves
      // we do not do the moving over here as we are the caller of the unparser.
      //
    }

    state.groupIndexStack.pop()
    //
    // this is establishing the invariant that unparsers (in this case the sequence unparser)
    // moves over within its containing group. The caller of an unparser does not do this move.
    //
    // state.moveOverOneGroupIndexOnly() // move past this sequence itself, next group child it ITS parent.
  }