View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.text;
18  
19  import static java.util.FormattableFlags.LEFT_JUSTIFY;
20  
21  import java.util.Formattable;
22  import java.util.Formatter;
23  
24  import org.apache.commons.lang3.StringUtils;
25  
26  /**
27   * Provides utilities for working with the {@code Formattable} interface.
28   *
29   * <p>
30   * The {@link Formattable} interface provides basic control over formatting when using a {@code Formatter}. It is primarily concerned with numeric precision and
31   * padding, and is not designed to allow generalized alternate formats.
32   * </p>
33   *
34   * @since 1.0
35   */
36  public class FormattableUtils {
37  
38      /**
39       * A format that simply outputs the value as a string.
40       */
41      private static final String SIMPLEST_FORMAT = "%s";
42  
43      /**
44       * Handles the common {@code Formattable} operations of truncate-pad-append, with no ellipsis on precision overflow, and padding width underflow with
45       * spaces.
46       *
47       * @param seq       the string to handle, not null.
48       * @param formatter the destination formatter, not null.
49       * @param flags     the flags for formatting, see {@code Formattable}.
50       * @param width     the width of the output, see {@code Formattable}.
51       * @param precision the precision of the output, see {@code Formattable}.
52       * @return The {@code formatter} instance, not null.
53       */
54      public static Formatter append(final CharSequence seq, final Formatter formatter, final int flags, final int width,
55              final int precision) {
56          return append(seq, formatter, flags, width, precision, ' ', null);
57      }
58  
59      /**
60       * Handles the common {@link Formattable} operations of truncate-pad-append, with no ellipsis on precision overflow.
61       *
62       * @param seq       the string to handle, not null.
63       * @param formatter the destination formatter, not null.
64       * @param flags     the flags for formatting, see {@code Formattable}.
65       * @param width     the width of the output, see {@code Formattable}.
66       * @param precision the precision of the output, see {@code Formattable}.
67       * @param padChar   the pad character to use.
68       * @return The {@code formatter} instance, not null.
69       */
70      public static Formatter append(final CharSequence seq, final Formatter formatter, final int flags, final int width,
71              final int precision, final char padChar) {
72          return append(seq, formatter, flags, width, precision, padChar, null);
73      }
74  
75      /**
76       * Handles the common {@link Formattable} operations of truncate-pad-append.
77       *
78       * @param seq              the string to handle, not null.
79       * @param formatter        the destination formatter, not null.
80       * @param flags            the flags for formatting, see {@code Formattable}.
81       * @param width            the width of the output, see {@code Formattable}.
82       * @param precision        the precision of the output, see {@code Formattable}.
83       * @param padChar          the pad character to use.
84       * @param truncateEllipsis the ellipsis to use when precision dictates truncation, null or empty causes a hard truncation.
85       * @return The {@code formatter} instance, not null.
86       * @throws IllegalArgumentException if {@code ellipsis.length() > precision}, given that {@code ellipsis} is not null and {@code precision >= 0}.
87       */
88      public static Formatter append(final CharSequence seq, final Formatter formatter, final int flags, final int width,
89              final int precision, final char padChar, final CharSequence truncateEllipsis) {
90          if (!(truncateEllipsis == null || precision < 0 || truncateEllipsis.length() <= precision)) {
91              throw new IllegalArgumentException(
92                      String.format("Specified ellipsis '%s' exceeds precision of %s",
93                              truncateEllipsis,
94                              precision));
95          }
96          final StringBuilder buf = new StringBuilder(seq);
97          if (precision >= 0 && precision < seq.length()) {
98              final CharSequence ellipsis;
99              if (truncateEllipsis == null) {
100                 ellipsis = StringUtils.EMPTY;
101             } else {
102                 ellipsis = truncateEllipsis;
103             }
104             buf.replace(precision - ellipsis.length(), seq.length(), ellipsis.toString());
105         }
106         final boolean leftJustify = (flags & LEFT_JUSTIFY) == LEFT_JUSTIFY;
107         for (int i = buf.length(); i < width; i++) {
108             buf.insert(leftJustify ? i : 0, padChar);
109         }
110         formatter.format(buf.toString());
111         return formatter;
112     }
113 
114     /**
115      * Handles the common {@link Formattable} operations of truncate-pad-append, padding width underflow with spaces.
116      *
117      * @param seq       the string to handle, not null.
118      * @param formatter the destination formatter, not null.
119      * @param flags     the flags for formatting, see {@code Formattable}.
120      * @param width     the width of the output, see {@code Formattable}.
121      * @param precision the precision of the output, see {@code Formattable}.
122      * @param ellipsis  the ellipsis to use when precision dictates truncation, null or empty causes a hard truncation..
123      * @return The {@code formatter} instance, not null
124      * @throws IllegalArgumentException if {@code ellipsis.length() > precision}, given that {@code ellipsis} is not null and {@code precision >= 0}.
125      */
126     public static Formatter append(final CharSequence seq, final Formatter formatter, final int flags, final int width, final int precision,
127             final CharSequence ellipsis) {
128         return append(seq, formatter, flags, width, precision, ' ', ellipsis);
129     }
130 
131     /**
132      * Gets the default formatted representation of the specified {@code Formattable}.
133      *
134      * @param formattable the instance to convert to a string, not null.
135      * @return The resulting string, not null.
136      */
137     public static String toString(final Formattable formattable) {
138         return String.format(SIMPLEST_FORMAT, formattable);
139     }
140 
141     /**
142      * {@code FormattableUtils} instances should NOT be constructed in standard programming. Instead, the methods of the class should be invoked statically.
143      *
144      * <p>
145      * This constructor is public to permit tools that require a JavaBean instance to operate.
146      * </p>
147      */
148     public FormattableUtils() {
149     }
150 
151 }