@Override
  public void checkThisValue(
      final CompilationTimeStamp timestamp,
      final IValue value,
      final ValueCheckingOptions valueCheckingOptions) {
    super.checkThisValue(timestamp, value, valueCheckingOptions);

    IValue last = value.getValueRefdLast(timestamp, valueCheckingOptions.expected_value, null);
    if (null == last || last.getIsErroneous(timestamp)) {
      return;
    }

    // already handled ones
    switch (value.getValuetype()) {
      case OMIT_VALUE:
      case REFERENCED_VALUE:
        return;
      case UNDEFINED_LOWERIDENTIFIER_VALUE:
        if (Value_type.REFERENCED_VALUE.equals(last.getValuetype())) {
          return;
        }
        break;
      default:
        break;
    }

    switch (last.getValuetype()) {
      case UNDEFINED_BLOCK:
        last = last.setValuetype(timestamp, Value_type.CHARSYMBOLS_VALUE);
        if (last.getIsErroneous(timestamp)) {
          return;
        }

        last.setValuetype(timestamp, Value_type.UNIVERSALCHARSTRING_VALUE);
        break;
      case CHARSYMBOLS_VALUE:
      case CHARSTRING_VALUE:
        last.setValuetype(timestamp, Value_type.UNIVERSALCHARSTRING_VALUE);
        break;
      case ISO2022STRING_VALUE:
        location.reportSemanticError(UniversalCharstring_Value.ISOCONVERTION);
        setIsErroneous(true);
        break;
      case UNIVERSALCHARSTRING_VALUE:
        break;
      case EXPRESSION_VALUE:
      case MACRO_VALUE:
        // already checked
        break;
      default:
        value.getLocation().reportSemanticError(BMPSTRINGVALUEEXPECTED);
        value.setIsErroneous(true);
    }
  }
  @Override
  public void checkThisValue(
      final CompilationTimeStamp timestamp,
      final IValue value,
      final ValueCheckingOptions valueCheckingOptions) {
    if (getIsErroneous(timestamp)) {
      return;
    }

    super.checkThisValue(timestamp, value, valueCheckingOptions);

    IValue last = value.getValueRefdLast(timestamp, valueCheckingOptions.expected_value, null);
    if (last == null || last.getIsErroneous(timestamp)) {
      return;
    }

    // already handled ones
    switch (value.getValuetype()) {
      case OMIT_VALUE:
      case REFERENCED_VALUE:
        return;
      case UNDEFINED_LOWERIDENTIFIER_VALUE:
        if (Value_type.REFERENCED_VALUE.equals(last.getValuetype())) {
          return;
        }
        break;
      default:
        break;
    }

    if (Value_type.UNDEFINED_BLOCK.equals(last.getValuetype())) {
      last = last.setValuetype(timestamp, Value_type.SEQUENCEOF_VALUE);
    }
    if (last.getIsErroneous(timestamp)) {
      return;
    }

    switch (last.getValuetype()) {
      case SEQUENCEOF_VALUE:
        {
          checkThisValueSequenceOf(
              timestamp,
              (SequenceOf_Value) last,
              valueCheckingOptions.expected_value,
              valueCheckingOptions.incomplete_allowed,
              valueCheckingOptions.implicit_omit,
              valueCheckingOptions.str_elem);
          break;
        }
      case SETOF_VALUE:
        {
          checkThisValueSetOf(
              timestamp,
              (SetOf_Value) last,
              valueCheckingOptions.expected_value,
              valueCheckingOptions.incomplete_allowed,
              valueCheckingOptions.implicit_omit,
              valueCheckingOptions.str_elem);
          break;
        }
      case EXPRESSION_VALUE:
      case MACRO_VALUE:
        // already checked
        break;
      default:
        if (value.isAsn()) {
          value.getLocation().reportSemanticError(SEQOFVALUEEXPECTED);
        } else {
          value.getLocation().reportSemanticError(RECORDOFVALUEEXPECTED);
        }

        value.setIsErroneous(true);
    }

    if (valueCheckingOptions.sub_check) {
      // there is no parent type to check
      if (subType != null) {
        subType.checkThisValue(timestamp, last);
      }
    }
  }