001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017
018package org.apache.logging.log4j.core.pattern;
019
020import org.apache.logging.log4j.util.PerformanceSensitive;
021
022/**
023 * Modifies the output of a pattern converter for a specified minimum and maximum width and alignment.
024 */
025@PerformanceSensitive("allocation")
026public final class FormattingInfo {
027    /**
028     * Array of spaces.
029     */
030    private static final char[] SPACES = new char[] { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
031
032    /**
033     * Array of zeros.
034     */
035    private static final char[] ZEROS = new char[] { '0', '0', '0', '0', '0', '0', '0', '0' };
036
037    /**
038     * Default instance.
039     */
040    private static final FormattingInfo DEFAULT = new FormattingInfo(false, 0, Integer.MAX_VALUE, true);
041
042    /**
043     * Minimum length.
044     */
045    private final int minLength;
046
047    /**
048     * Maximum length.
049     */
050    private final int maxLength;
051
052    /**
053     * Alignment.
054     */
055    private final boolean leftAlign;
056
057    /**
058     * Left vs. right-hand side truncation.
059     */
060    private final boolean leftTruncate;
061
062    /**
063     * Use zero-padding instead whitespace padding
064     */
065    private final boolean zeroPad;
066
067    /**
068     * Creates new instance.
069     *
070     * @param leftAlign
071     *            left align if true.
072     * @param minLength
073     *            minimum length.
074     * @param maxLength
075     *            maximum length.
076     * @param leftTruncate
077     *            truncates to the left if true
078     */
079    public FormattingInfo(final boolean leftAlign, final int minLength, final int maxLength, final boolean leftTruncate) {
080        this(leftAlign, minLength, maxLength, leftTruncate, false);
081    }
082
083    /**
084     * Creates new instance.
085     *
086     * @param leftAlign
087     *            left align if true.
088     * @param minLength
089     *            minimum length.
090     * @param maxLength
091     *            maximum length.
092     * @param leftTruncate
093     *            truncates to the left if true
094     * @param zeroPad
095     *            use zero-padding instead of whitespace-padding
096     */
097    public FormattingInfo(final boolean leftAlign, final int minLength, final int maxLength, final boolean leftTruncate, final boolean zeroPad) {
098        this.leftAlign = leftAlign;
099        this.minLength = minLength;
100        this.maxLength = maxLength;
101        this.leftTruncate = leftTruncate;
102        this.zeroPad = zeroPad;
103    }
104
105    /**
106     * Gets default instance.
107     *
108     * @return default instance.
109     */
110    public static FormattingInfo getDefault() {
111        return DEFAULT;
112    }
113
114    /**
115     * Determine if left aligned.
116     *
117     * @return true if left aligned.
118     */
119    public boolean isLeftAligned() {
120        return leftAlign;
121    }
122
123    /**
124     * Determine if left truncated.
125     *
126     * @return true if left truncated.
127     */
128    public boolean isLeftTruncate() {
129                return leftTruncate;
130        }
131
132    /**
133     * Determine if zero-padded.
134     *
135     * @return true if zero-padded.
136     */
137    public boolean isZeroPad() {
138        return zeroPad;
139    }
140
141    /**
142     * Get minimum length.
143     *
144     * @return minimum length.
145     */
146    public int getMinLength() {
147        return minLength;
148    }
149
150    /**
151     * Get maximum length.
152     *
153     * @return maximum length.
154     */
155    public int getMaxLength() {
156        return maxLength;
157    }
158
159    /**
160     * Adjust the content of the buffer based on the specified lengths and alignment.
161     *
162     * @param fieldStart
163     *            start of field in buffer.
164     * @param buffer
165     *            buffer to be modified.
166     */
167    public void format(final int fieldStart, final StringBuilder buffer) {
168        final int rawLength = buffer.length() - fieldStart;
169
170        if (rawLength > maxLength) {
171                        if (leftTruncate) {
172                                buffer.delete(fieldStart, buffer.length() - maxLength);
173                        } else {
174                                buffer.delete(fieldStart + maxLength, fieldStart + buffer.length());
175                        }
176        } else if (rawLength < minLength) {
177            if (leftAlign) {
178                final int fieldEnd = buffer.length();
179                buffer.setLength(fieldStart + minLength);
180
181                for (int i = fieldEnd; i < buffer.length(); i++) {
182                    buffer.setCharAt(i, ' ');
183                }
184            } else {
185                int padLength = minLength - rawLength;
186
187                final char[] paddingArray= zeroPad ? ZEROS : SPACES;
188
189                for (; padLength > paddingArray.length; padLength -= paddingArray.length) {
190                    buffer.insert(fieldStart, paddingArray);
191                }
192
193                buffer.insert(fieldStart, paddingArray, 0, padLength);
194            }
195        }
196    }
197
198    /**
199     * Returns a String suitable for debugging.
200     *
201     * @return a String suitable for debugging.
202     */
203    @Override
204    public String toString() {
205        final StringBuilder sb = new StringBuilder();
206        sb.append(super.toString());
207        sb.append("[leftAlign=");
208        sb.append(leftAlign);
209        sb.append(", maxLength=");
210        sb.append(maxLength);
211        sb.append(", minLength=");
212        sb.append(minLength);
213        sb.append(", leftTruncate=");
214        sb.append(leftTruncate);
215        sb.append(", zeroPad=");
216        sb.append(zeroPad);
217        sb.append(']');
218        return sb.toString();
219    }
220
221}