def readVariable()

in daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/VariableMap1.scala [360:427]


  def readVariable(
    vrd: VariableRuntimeData,
    referringContext: ThrowsSDE,
    state: ParseOrUnparseState
  ): DataValuePrimitive = {
    val varQName = vrd.globalQName
    vrd.direction match {
      case VariableDirection.ParseOnly if (!state.isInstanceOf[PState]) =>
        state.SDE(
          "Attempting to read variable %s which is marked as parseOnly during unparsing".format(
            varQName
          )
        )
      case VariableDirection.UnparseOnly if (!state.isInstanceOf[UState]) =>
        state.SDE(
          "Attempting to read variable %s which is marked as unparseOnly during parsing".format(
            varQName
          )
        )
      case _ => // Do nothing
    }

    val variable = {
      // The vrd.vmapIndex cannot be out of range of the vTable, because the vTable size
      // accommodates as many variables as are in the top-level schema.
      val varAtIndex = vTable(vrd.vmapIndex).head
      val varAtIndexVRD = varAtIndex.rd
      if (varAtIndexVRD != vrd) {
        // The variable at that index does not have our VRD.
        // A newVariableInstance must be in place for this variable, but we're trying to access
        // using a different VRD (probably the top-level VRD you get from the schemaSet variable map.
        // These MUST, however, be for the same variable, and so will have the same index
        // into the vtable.
        Assert.invariant(
          (varAtIndexVRD eq vrd) || (varAtIndexVRD.globalQName eq vrd.globalQName)
        )
      }
      varAtIndex
    }
    variable.state match {
      case VariableRead if (variable.value.isDefined) => variable.value.getNonNullable
      case VariableDefined | VariableSet if (variable.value.isDefined) => {
        variable.setState(VariableRead)
        variable.value.getNonNullable
      }
      // This case is only hit for defineVariable's who's expression reference
      // other defineVariables with expressions. It will be hit at the start
      // of parsing, before an infoset is generated, via the
      // forceExpressionEvaluations function after which all variables should
      // have a defined value
      case VariableUndefined if (variable.rd.maybeDefaultValueExpr.isDefined) => {
        variable.setState(VariableBeingDefined)
        val res =
          DataValue.unsafeFromAnyRef(variable.rd.maybeDefaultValueExpr.get.evaluate(state))

        // Need to update the variable's value with the result of the
        // expression
        variable.setState(VariableRead)
        variable.setValue(res)

        res
      }
      case VariableBeingDefined => throw new VariableCircularDefinition(varQName, vrd)
      case VariableInProcess => throw new VariableSuspended(varQName, vrd)
      case _ =>
        throw new VariableHasNoValue(varQName, vrd)
    }
  }