AbstractPatternFormatter.java

1
/*
2
 * Copyright 2004 the original author or authors.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.ancientprogramming.fixedformat4j.format.impl;
17
18
import com.ancientprogramming.fixedformat4j.format.AbstractFixedFormatter;
19
import com.ancientprogramming.fixedformat4j.format.FormatInstructions;
20
21
import java.util.Map;
22
import java.util.concurrent.ConcurrentHashMap;
23
24
/**
25
 * Base class for pattern-based date/time formatters.
26
 *
27
 * <p>Overrides {@link #stripPadding} to restore padding characters that belong
28
 * to the date/time value rather than to the field padding. This is necessary when
29
 * {@code paddingChar} equals a character that can also appear within a formatted date
30
 * (e.g. {@code '0'} with a pattern like {@code yyyyMMddHHmmss} where seconds may be
31
 * {@code 00}).
32
 *
33
 * <p>After stripping padding, if the result is shorter than the formatted output length
34
 * for the pattern, it is re-padded to that length so that the underlying date parser
35
 * receives a well-formed string.
36
 *
37
 * @param <T> the date/time type handled by this formatter
38
 * @author Jacob von Eyben - <a href="https://eybenconsult.com">https://eybenconsult.com</a>
39
 * @since 1.6.1
40
 */
41
public abstract class AbstractPatternFormatter<T> extends AbstractFixedFormatter<T> {
42
43
  private static final Map<Class<?>, Map<String, Integer>> PATTERN_LENGTH_CACHE = new ConcurrentHashMap<>();
44
45
  /**
46
   * Strips padding, then re-applies it when the padding character overlaps with
47
   * characters that are significant in the date/time pattern.
48
   *
49
   * <p>For example, with padding {@code '0'} and pattern {@code yyyyMMddHHmmss},
50
   * a field value of {@code "00"} (seconds) would otherwise be stripped to an empty
51
   * string, making the date un-parseable. This override detects that case and
52
   * restores the stripped characters before returning.
53
   *
54
   * <p>{@inheritDoc}
55
   */
56
  @Override
57
  protected String stripPadding(String value, FormatInstructions instructions) {
58
    String stripped = instructions.getAlignment().remove(value, instructions.getPaddingChar());
59 1 1. stripPadding : negated conditional → KILLED
    if (stripped.isEmpty()) {
60 1 1. stripPadding : replaced return value with "" for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::stripPadding → SURVIVED
      return stripped;
61
    }
62
    String pattern = instructions.getFixedFormatPatternData().getPattern();
63
    int formattedLength = formattedLengthForPattern(pattern);
64 2 1. stripPadding : changed conditional boundary → SURVIVED
2. stripPadding : negated conditional → KILLED
    if (stripped.length() < formattedLength) {
65 1 1. stripPadding : replaced return value with "" for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::stripPadding → KILLED
      return instructions.getAlignment().apply(stripped, formattedLength, instructions.getPaddingChar());
66
    }
67 1 1. stripPadding : replaced return value with "" for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::stripPadding → KILLED
    return stripped;
68
  }
69
70
  /**
71
   * @deprecated Use {@link #stripPadding} instead. This method will be removed in 1.7.0.
72
   * @see AbstractFixedFormatter#getRemovePadding
73
   */
74
  @Deprecated
75
  @Override
76
  protected String getRemovePadding(String value, FormatInstructions instructions) {
77 1 1. getRemovePadding : replaced return value with "" for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::getRemovePadding → KILLED
    return stripPadding(value, instructions);
78
  }
79
80
  protected final int formattedLengthForPattern(String pattern) {
81 1 1. formattedLengthForPattern : replaced int return with 0 for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::formattedLengthForPattern → KILLED
    return PATTERN_LENGTH_CACHE
82 1 1. lambda$formattedLengthForPattern$0 : replaced return value with Collections.emptyMap for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::lambda$formattedLengthForPattern$0 → SURVIVED
        .computeIfAbsent(getClass(), k -> new ConcurrentHashMap<>())
83
        .computeIfAbsent(pattern, this::computeFormattedLengthForPattern);
84
  }
85
86
  /**
87
   * Returns the number of characters that this formatter's pattern produces when applied
88
   * to any date/time value. Used to restore padding characters that are part of the
89
   * date/time value rather than field padding.
90
   *
91
   * <p>This method is called at most once per (formatter type, pattern) pair; results are
92
   * cached by {@link #formattedLengthForPattern}.
93
   *
94
   * @param pattern the date/time pattern string
95
   * @return the fixed character length of the formatted output
96
   */
97
  protected abstract int computeFormattedLengthForPattern(String pattern);
98
}

Mutations

59

1.1
Location : stripPadding
Killed by : com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateFormatter.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateFormatter]/[method:testAllSpaceInputParsesToNull()]
negated conditional → KILLED

60

1.1
Location : stripPadding
Killed by : none
replaced return value with "" for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::stripPadding → SURVIVED
Covering tests

64

1.1
Location : stripPadding
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

2.2
Location : stripPadding
Killed by : com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter]/[method:leftAlignedZeroPaddingDoesNotStripZeroValuedTimeComponents()]
negated conditional → KILLED

65

1.1
Location : stripPadding
Killed by : com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter]/[method:leftAlignedZeroPaddingDoesNotStripZeroValuedTimeComponents()]
replaced return value with "" for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::stripPadding → KILLED

67

1.1
Location : stripPadding
Killed by : com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter]/[method:testParseWithSpaceSeparator()]
replaced return value with "" for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::stripPadding → KILLED

77

1.1
Location : getRemovePadding
Killed by : com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter]/[method:testParseWithSpaceSeparator()]
replaced return value with "" for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::getRemovePadding → KILLED

81

1.1
Location : formattedLengthForPattern
Killed by : com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter.[engine:junit-jupiter]/[class:com.ancientprogramming.fixedformat4j.format.impl.TestLocalDateTimeFormatter]/[method:leftAlignedZeroPaddingDoesNotStripZeroValuedTimeComponents()]
replaced int return with 0 for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::formattedLengthForPattern → KILLED

82

1.1
Location : lambda$formattedLengthForPattern$0
Killed by : none
replaced return value with Collections.emptyMap for com/ancientprogramming/fixedformat4j/format/impl/AbstractPatternFormatter::lambda$formattedLengthForPattern$0 → SURVIVED
Covering tests

Active mutators

Tests examined


Report generated by PIT 1.17.1