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 * http://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.lang3.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.ObjectUtils;
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.commons.lang3.Validate;
27
28 /**
29 * <p>Provides utilities for working with the {@code Formattable} interface.</p>
30 *
31 * <p>The {@link Formattable} interface provides basic control over formatting
32 * when using a {@code Formatter}. It is primarily concerned with numeric precision
33 * and padding, and is not designed to allow generalised alternate formats.</p>
34 *
35 * @since Lang 3.0
36 * @version $Id: FormattableUtils.java 1436770 2013-01-22 07:09:45Z ggregory $
37 */
38 public class FormattableUtils {
39
40 /**
41 * A format that simply outputs the value as a string.
42 */
43 private static final String SIMPLEST_FORMAT = "%s";
44
45 /**
46 * <p>{@code FormattableUtils} instances should NOT be constructed in
47 * standard programming. Instead, the methods of the class should be invoked
48 * statically.</p>
49 *
50 * <p>This constructor is public to permit tools that require a JavaBean
51 * instance to operate.</p>
52 */
53 public FormattableUtils() {
54 super();
55 }
56
57 //-----------------------------------------------------------------------
58 /**
59 * Get the default formatted representation of the specified
60 * {@code Formattable}.
61 *
62 * @param formattable the instance to convert to a string, not null
63 * @return the resulting string, not null
64 */
65 public static String toString(final Formattable formattable) {
66 return String.format(SIMPLEST_FORMAT, formattable);
67 }
68
69 /**
70 * Handles the common {@code Formattable} operations of truncate-pad-append,
71 * with no ellipsis on precision overflow, and padding width underflow with
72 * spaces.
73 *
74 * @param seq the string to handle, not null
75 * @param formatter the destination formatter, not null
76 * @param flags the flags for formatting, see {@code Formattable}
77 * @param width the width of the output, see {@code Formattable}
78 * @param precision the precision of the output, see {@code Formattable}
79 * @return the {@code formatter} instance, not null
80 */
81 public static Formatter append(final CharSequence seq, final Formatter formatter, final int flags, final int width,
82 final int precision) {
83 return append(seq, formatter, flags, width, precision, ' ', null);
84 }
85
86 /**
87 * Handles the common {@link Formattable} operations of truncate-pad-append,
88 * with no ellipsis on precision overflow.
89 *
90 * @param seq the string to handle, not null
91 * @param formatter the destination formatter, not null
92 * @param flags the flags for formatting, see {@code Formattable}
93 * @param width the width of the output, see {@code Formattable}
94 * @param precision the precision of the output, see {@code Formattable}
95 * @param padChar the pad character to use
96 * @return the {@code formatter} instance, not null
97 */
98 public static Formatter append(final CharSequence seq, final Formatter formatter, final int flags, final int width,
99 final int precision, final char padChar) {
100 return append(seq, formatter, flags, width, precision, padChar, null);
101 }
102
103 /**
104 * Handles the common {@link Formattable} operations of truncate-pad-append,
105 * padding width underflow with spaces.
106 *
107 * @param seq the string to handle, not null
108 * @param formatter the destination formatter, not null
109 * @param flags the flags for formatting, see {@code Formattable}
110 * @param width the width of the output, see {@code Formattable}
111 * @param precision the precision of the output, see {@code Formattable}
112 * @param ellipsis the ellipsis to use when precision dictates truncation, null or
113 * empty causes a hard truncation
114 * @return the {@code formatter} instance, not null
115 */
116 public static Formatter append(final CharSequence seq, final Formatter formatter, final int flags, final int width,
117 final int precision, final CharSequence ellipsis) {
118 return append(seq, formatter, flags, width, precision, ' ', ellipsis);
119 }
120
121 /**
122 * Handles the common {@link Formattable} operations of truncate-pad-append.
123 *
124 * @param seq the string to handle, not null
125 * @param formatter the destination formatter, not null
126 * @param flags the flags for formatting, see {@code Formattable}
127 * @param width the width of the output, see {@code Formattable}
128 * @param precision the precision of the output, see {@code Formattable}
129 * @param padChar the pad character to use
130 * @param ellipsis the ellipsis to use when precision dictates truncation, null or
131 * empty causes a hard truncation
132 * @return the {@code formatter} instance, not null
133 */
134 public static Formatter append(final CharSequence seq, final Formatter formatter, final int flags, final int width,
135 final int precision, final char padChar, final CharSequence ellipsis) {
136 Validate.isTrue(ellipsis == null || precision < 0 || ellipsis.length() <= precision,
137 "Specified ellipsis '%1$s' exceeds precision of %2$s", ellipsis, Integer.valueOf(precision));
138 final StringBuilder buf = new StringBuilder(seq);
139 if (precision >= 0 && precision < seq.length()) {
140 final CharSequence _ellipsis = ObjectUtils.defaultIfNull(ellipsis, StringUtils.EMPTY);
141 buf.replace(precision - _ellipsis.length(), seq.length(), _ellipsis.toString());
142 }
143 final boolean leftJustify = (flags & LEFT_JUSTIFY) == LEFT_JUSTIFY;
144 for (int i = buf.length(); i < width; i++) {
145 buf.insert(leftJustify ? i : 0, padChar);
146 }
147 formatter.format(buf.toString());
148 return formatter;
149 }
150
151 }