Example #1
0
  @Override
  public void parse(
      CharSequence text,
      ParseLog status,
      AttributeQuery attributes,
      Map<ChronoElement<?>, Object> parsedResult,
      FormatStep step) {

    int start = status.getPosition();
    int len = text.length();

    int protectedChars =
        step.getAttribute(Attributes.PROTECTED_CHARACTERS, attributes, 0).intValue();

    if (protectedChars > 0) {
      len -= protectedChars;
    }

    if (start >= len) {
      status.setError(start, "Missing chars for: " + this.element.name());
      status.setWarning();
      return;
    }

    TextElement<?> te = TextElement.class.cast(this.element);
    Object value = te.parse(text, status.getPP(), step.getQuery(attributes));

    if (status.isError()) {
      Class<V> valueType = this.element.getType();
      if (valueType.isEnum()) {
        status.setError(status.getErrorIndex(), "No suitable enum found: " + valueType.getName());
      }
    } else {
      if (value == null) {
        status.setError(start, "No interpretable value.");
      } else {
        parsedResult.put(this.element, value);
      }
    }
  }
  @Override
  public void print(
      ChronoDisplay formattable,
      Appendable buffer,
      AttributeQuery attributes,
      Set<ElementPosition> positions, // optional
      FormatStep step)
      throws IOException {

    BigDecimal value = toDecimal(formattable.get(this.element));
    BigDecimal min = toDecimal(formattable.getMinimum(this.element));
    BigDecimal max = toDecimal(formattable.getMaximum(this.element));

    if (value.compareTo(max) > 0) {
      value = max;
    }

    BigDecimal fraction =
        value.subtract(min).divide(max.subtract(min).add(BigDecimal.ONE), 9, RoundingMode.FLOOR);

    fraction =
        ((fraction.compareTo(BigDecimal.ZERO) == 0)
            ? BigDecimal.ZERO
            : fraction.stripTrailingZeros());

    char zeroDigit =
        step.getAttribute(Attributes.ZERO_DIGIT, attributes, Character.valueOf('0')).charValue();

    int start = -1;
    int printed = 0;

    if (buffer instanceof CharSequence) {
      start = ((CharSequence) buffer).length();
    }

    if (fraction.scale() == 0) {
      // scale ist 0, wenn value das Minimum ist
      if (this.minDigits > 0) {
        if (this.hasDecimalSeparator()) {
          this.decimalSeparator.print(formattable, buffer, attributes, positions, step);
          printed++;
        }

        for (int i = 0; i < this.minDigits; i++) {
          buffer.append(zeroDigit);
        }

        printed += this.minDigits;
      }
    } else {
      if (this.hasDecimalSeparator()) {
        this.decimalSeparator.print(formattable, buffer, attributes, positions, step);
        printed++;
      }

      int outputScale = Math.min(Math.max(fraction.scale(), this.minDigits), this.maxDigits);
      fraction = fraction.setScale(outputScale, RoundingMode.FLOOR);
      String digits = fraction.toPlainString();
      int diff = zeroDigit - '0';

      for (int i = 2, n = digits.length(); i < n; i++) {
        char c = (char) (digits.charAt(i) + diff);
        buffer.append(c);
        printed++;
      }
    }

    if ((start != -1) && (printed > 1) && (positions != null)) {
      positions.add( // Zählung ohne Dezimaltrennzeichen
          new ElementPosition(this.element, start + 1, start + printed));
    }
  }
  @Override
  public void parse(
      CharSequence text,
      ParseLog status,
      AttributeQuery attributes,
      Map<ChronoElement<?>, Object> parsedResult,
      FormatStep step) {

    Leniency leniency = step.getAttribute(Attributes.LENIENCY, attributes, Leniency.SMART);

    int effectiveMin = 0;
    int effectiveMax = 9;

    if (!leniency.isLax() || this.fixedWidth) {
      effectiveMin = this.minDigits;
      effectiveMax = this.maxDigits;
    }

    int len = text.length();

    if (status.getPosition() >= len) {
      if (effectiveMin > 0) {
        status.setError(
            status.getPosition(), "Expected fraction digits not found for: " + this.element.name());
      }
      return;
    }

    if (this.hasDecimalSeparator()) {
      this.decimalSeparator.parse(text, status, attributes, null, step);

      if (status.isError()) {
        if (effectiveMin == 0) {
          status.clearError();
        }
        return;
      }
    }

    int current = status.getPosition();
    int minEndPos = current + effectiveMin;
    int maxEndPos = Math.min(current + effectiveMax, len);

    if (minEndPos > len) {
      status.setError(status.getPosition(), "Expected at least " + effectiveMin + " digits.");
      return;
    }

    char zeroDigit =
        step.getAttribute(Attributes.ZERO_DIGIT, attributes, Character.valueOf('0')).charValue();

    long total = 0;

    while (current < maxEndPos) {
      int digit = text.charAt(current) - zeroDigit;

      if ((digit >= 0) && (digit <= 9)) {
        total = total * 10 + digit;
        current++;
      } else if (current < minEndPos) {
        status.setError(status.getPosition(), "Expected at least " + effectiveMin + " digits.");
        return;
      } else {
        break;
      }
    }

    BigDecimal fraction = new BigDecimal(total);
    fraction = fraction.movePointLeft(current - status.getPosition());

    if (this.element.name().equals("NANO_OF_SECOND")) {
      Integer min = Integer.valueOf(0);
      Integer max = MRD_MINUS_1;
      Integer num = this.getRealValue(fraction, min, max);
      parsedResult.put(this.element, num);
    } else {
      // hier nur prototypischer Wert, später fraktionalen Wert bestimmen
      parsedResult.put(FractionalElement.FRACTION, fraction);
      parsedResult.put(this.element, this.element.getDefaultMinimum());
    }

    status.setPosition(current);
  }