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     * Default instance.
034     */
035    private static final FormattingInfo DEFAULT = new FormattingInfo(false, 0, Integer.MAX_VALUE, true);
036
037    /**
038     * Minimum length.
039     */
040    private final int minLength;
041
042    /**
043     * Maximum length.
044     */
045    private final int maxLength;
046
047    /**
048     * Alignment.
049     */
050    private final boolean leftAlign;
051
052    /**
053     * Left vs. right-hand side truncation.
054     */
055    private final boolean leftTruncate;
056
057    /**
058     * Creates new instance.
059     *
060     * @param leftAlign
061     *            left align if true.
062     * @param minLength
063     *            minimum length.
064     * @param maxLength
065     *            maximum length.
066     * @param leftTruncate
067     *            truncates to the left if true
068     */
069    public FormattingInfo(final boolean leftAlign, final int minLength, final int maxLength, final boolean leftTruncate) {
070        this.leftAlign = leftAlign;
071        this.minLength = minLength;
072        this.maxLength = maxLength;
073        this.leftTruncate = leftTruncate;
074    }
075
076    /**
077     * Gets default instance.
078     *
079     * @return default instance.
080     */
081    public static FormattingInfo getDefault() {
082        return DEFAULT;
083    }
084
085    /**
086     * Determine if left aligned.
087     *
088     * @return true if left aligned.
089     */
090    public boolean isLeftAligned() {
091        return leftAlign;
092    }
093
094    /**
095     * Determine if left truncated.
096     *
097     * @return true if left truncated.
098     */
099    public boolean isLeftTruncate() {
100                return leftTruncate;
101        }
102
103    /**
104     * Get minimum length.
105     *
106     * @return minimum length.
107     */
108    public int getMinLength() {
109        return minLength;
110    }
111
112    /**
113     * Get maximum length.
114     *
115     * @return maximum length.
116     */
117    public int getMaxLength() {
118        return maxLength;
119    }
120
121    /**
122     * Adjust the content of the buffer based on the specified lengths and alignment.
123     *
124     * @param fieldStart
125     *            start of field in buffer.
126     * @param buffer
127     *            buffer to be modified.
128     */
129    public void format(final int fieldStart, final StringBuilder buffer) {
130        final int rawLength = buffer.length() - fieldStart;
131
132        if (rawLength > maxLength) {
133                        if (leftTruncate) {
134                                buffer.delete(fieldStart, buffer.length() - maxLength);
135                        } else {
136                                buffer.delete(fieldStart + maxLength, fieldStart + buffer.length());
137                        }
138        } else if (rawLength < minLength) {
139            if (leftAlign) {
140                final int fieldEnd = buffer.length();
141                buffer.setLength(fieldStart + minLength);
142
143                for (int i = fieldEnd; i < buffer.length(); i++) {
144                    buffer.setCharAt(i, ' ');
145                }
146            } else {
147                int padLength = minLength - rawLength;
148
149                for (; padLength > SPACES.length; padLength -= SPACES.length) {
150                    buffer.insert(fieldStart, SPACES);
151                }
152
153                buffer.insert(fieldStart, SPACES, 0, padLength);
154            }
155        }
156    }
157
158    /**
159     * Returns a String suitable for debugging.
160     *
161     * @return a String suitable for debugging.
162     */
163    @Override
164    public String toString() {
165        final StringBuilder sb = new StringBuilder();
166        sb.append(super.toString());
167        sb.append("[leftAlign=");
168        sb.append(leftAlign);
169        sb.append(", maxLength=");
170        sb.append(maxLength);
171        sb.append(", minLength=");
172        sb.append(minLength);
173        sb.append(", leftTruncate=");
174        sb.append(leftTruncate);
175        sb.append(']');
176        return sb.toString();
177    }
178
179}