@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); }