/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache license, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the license for the specific language governing permissions and
 * limitations under the license.
 */
package org.apache.logging.log4j.core.pattern;

import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.util.PerformanceSensitive;


NameAbbreviator generates abbreviated logger and class names.
/** * NameAbbreviator generates abbreviated logger and class names. */
@PerformanceSensitive("allocation") public abstract class NameAbbreviator {
Default (no abbreviation) abbreviator.
/** * Default (no abbreviation) abbreviator. */
private static final NameAbbreviator DEFAULT = new NOPAbbreviator();
Gets an abbreviator.

For example, "%logger{2}" will output only 2 elements of the logger name, "%logger{1.}" will output only the first character of the non-final elements in the name, "%logger(1~.2~} will output the first character of the first element, two characters of the second and subsequent elements and will use a tilde to indicate abbreviated characters.

Params:
  • pattern – abbreviation pattern.
Returns:abbreviator, will not be null.
/** * Gets an abbreviator. * <p> * For example, "%logger{2}" will output only 2 elements of the logger name, "%logger{1.}" will output only the * first character of the non-final elements in the name, "%logger(1~.2~} will output the first character of the * first element, two characters of the second and subsequent elements and will use a tilde to indicate abbreviated * characters. * </p> * * @param pattern * abbreviation pattern. * @return abbreviator, will not be null. */
public static NameAbbreviator getAbbreviator(final String pattern) { if (pattern.length() > 0) { // if pattern is just spaces and numbers then // use MaxElementAbbreviator final String trimmed = pattern.trim(); if (trimmed.isEmpty()) { return DEFAULT; } boolean isNegativeNumber; final String number; // check if number is a negative number if (trimmed.length() > 1 && trimmed.charAt(0) == '-') { isNegativeNumber = true; number = trimmed.substring(1); } else { isNegativeNumber = false; number = trimmed; } int i = 0; while (i < number.length() && number.charAt(i) >= '0' && number.charAt(i) <= '9') { i++; } // // if all blanks and digits // if (i == number.length()) { return new MaxElementAbbreviator(Integer.parseInt(number), isNegativeNumber? MaxElementAbbreviator.Strategy.DROP : MaxElementAbbreviator.Strategy.RETAIN); } final ArrayList<PatternAbbreviatorFragment> fragments = new ArrayList<>(5); char ellipsis; int charCount; int pos = 0; while (pos < trimmed.length() && pos >= 0) { int ellipsisPos = pos; if (trimmed.charAt(pos) == '*') { charCount = Integer.MAX_VALUE; ellipsisPos++; } else { if (trimmed.charAt(pos) >= '0' && trimmed.charAt(pos) <= '9') { charCount = trimmed.charAt(pos) - '0'; ellipsisPos++; } else { charCount = 0; } } ellipsis = '\0'; if (ellipsisPos < trimmed.length()) { ellipsis = trimmed.charAt(ellipsisPos); if (ellipsis == '.') { ellipsis = '\0'; } } fragments.add(new PatternAbbreviatorFragment(charCount, ellipsis)); pos = trimmed.indexOf('.', pos); if (pos == -1) { break; } pos++; } return new PatternAbbreviator(fragments); } // // no matching abbreviation, return defaultAbbreviator // return DEFAULT; }
Gets default abbreviator.
Returns:default abbreviator.
/** * Gets default abbreviator. * * @return default abbreviator. */
public static NameAbbreviator getDefaultAbbreviator() { return DEFAULT; }
Abbreviates a name in a String.
Params:
  • original – the text to abbreviate, may not be null.
  • destination – StringBuilder to write the result to
/** * Abbreviates a name in a String. * * @param original the text to abbreviate, may not be null. * @param destination StringBuilder to write the result to */
public abstract void abbreviate(final String original, final StringBuilder destination);
Abbreviator that simply appends full name to buffer.
/** * Abbreviator that simply appends full name to buffer. */
private static class NOPAbbreviator extends NameAbbreviator {
Constructor.
/** * Constructor. */
public NOPAbbreviator() { }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void abbreviate(final String original, final StringBuilder destination) { destination.append(original); } }
Abbreviator that drops starting path elements.
/** * Abbreviator that drops starting path elements. */
private static class MaxElementAbbreviator extends NameAbbreviator {

When the name is reduced in length by cutting parts, there can be two ways to do it.

1. Remove a given number of parts starting from front - called DROP
2. Retain a given number of parts starting from the end - called RETAIN
/** * <p>When the name is reduced in length by cutting parts, there can be two ways to do it.</p> * 1. Remove a given number of parts starting from front - called DROP <br/> * 2. Retain a given number of parts starting from the end - called RETAIN */
private enum Strategy { DROP(0) { @Override void abbreviate(final int count, final String original, final StringBuilder destination) { // If a path does not contain enough path elements to drop, none will be dropped. int start = 0; int nextStart; for (int i = 0; i < count; i++) { nextStart = original.indexOf('.', start); if (nextStart == -1) { destination.append(original); return; } start = nextStart + 1; } destination.append(original, start, original.length()); } }, RETAIN(1) { @Override void abbreviate(final int count, final String original, final StringBuilder destination) { // We subtract 1 from 'len' when assigning to 'end' to avoid out of // bounds exception in return r.substring(end+1, len). This can happen if // precision is 1 and the category name ends with a dot. int end = original.length() - 1; for (int i = count; i > 0; i--) { end = original.lastIndexOf('.', end - 1); if (end == -1) { destination.append(original); return; } } destination.append(original, end + 1, original.length()); } }; final int minCount; Strategy(final int minCount) { this.minCount = minCount; } abstract void abbreviate(final int count, final String original, final StringBuilder destination); }
Maximum number of path elements to output.
/** * Maximum number of path elements to output. */
private final int count;
Strategy used for cutting down the size of the name
/** * Strategy used for cutting down the size of the name */
private final Strategy strategy;
Create new instance.
Params:
  • count – maximum number of path elements to drop or output.
  • strategy – drop or retain
/** * Create new instance. * * @param count maximum number of path elements to drop or output. * @param strategy drop or retain */
public MaxElementAbbreviator(final int count, final Strategy strategy) { this.count = Math.max(count, strategy.minCount); this.strategy = strategy; }
Abbreviate name.
Params:
  • original – The String to abbreviate.
  • destination – the buffer to write the abbreviated name into
/** * Abbreviate name. * * @param original The String to abbreviate. * @param destination the buffer to write the abbreviated name into */
@Override public void abbreviate(final String original, final StringBuilder destination) { strategy.abbreviate(count, original, destination); } }
Fragment of an pattern abbreviator.
/** * Fragment of an pattern abbreviator. */
private static class PatternAbbreviatorFragment {
Count of initial characters of element to output.
/** * Count of initial characters of element to output. */
private final int charCount;
Character used to represent dropped characters. '\0' indicates no representation of dropped characters.
/** * Character used to represent dropped characters. * '\0' indicates no representation of dropped characters. */
private final char ellipsis;
Creates a PatternAbbreviatorFragment.
Params:
  • charCount – number of initial characters to preserve.
  • ellipsis – character to represent elimination of characters, '\0' if no ellipsis is desired.
/** * Creates a PatternAbbreviatorFragment. * * @param charCount number of initial characters to preserve. * @param ellipsis character to represent elimination of characters, * '\0' if no ellipsis is desired. */
public PatternAbbreviatorFragment( final int charCount, final char ellipsis) { this.charCount = charCount; this.ellipsis = ellipsis; }
Abbreviate element of name.
Params:
  • buf – buffer to receive element.
  • startPos – starting index of name element.
Returns:starting index of next element.
/** * Abbreviate element of name. * * @param buf buffer to receive element. * @param startPos starting index of name element. * @return starting index of next element. */
public int abbreviate(final StringBuilder buf, final int startPos) { final int start = (startPos < 0) ? 0 : startPos; final int max = buf.length(); int nextDot = -1; for (int i = start; i < max; i++) { if (buf.charAt(i) == '.') { nextDot = i; break; } } if (nextDot != -1) { if (nextDot - startPos > charCount) { buf.delete(startPos + charCount, nextDot); nextDot = startPos + charCount; if (ellipsis != '\0') { buf.insert(nextDot, ellipsis); nextDot++; } } nextDot++; } return nextDot; } }
Pattern abbreviator.
/** * Pattern abbreviator. */
private static class PatternAbbreviator extends NameAbbreviator {
Element abbreviation patterns.
/** * Element abbreviation patterns. */
private final PatternAbbreviatorFragment[] fragments;
Create PatternAbbreviator.
Params:
  • fragments – element abbreviation patterns.
/** * Create PatternAbbreviator. * * @param fragments element abbreviation patterns. */
public PatternAbbreviator(final List<PatternAbbreviatorFragment> fragments) { if (fragments.isEmpty()) { throw new IllegalArgumentException( "fragments must have at least one element"); } this.fragments = new PatternAbbreviatorFragment[fragments.size()]; fragments.toArray(this.fragments); }
Abbreviates name.
Params:
  • original – the original string to abbreviate
  • destination – buffer that abbreviated name is appended to
/** * Abbreviates name. * * @param original the original string to abbreviate * @param destination buffer that abbreviated name is appended to */
@Override public void abbreviate(final String original, final StringBuilder destination) { // // all non-terminal patterns are executed once // int pos = destination.length(); final int max = pos + original.length(); destination.append(original); int fragmentIndex = 0; while (pos < max && pos >= 0) { pos = fragments[fragmentIndex].abbreviate(destination, pos); // last pattern in executed repeatedly if (fragmentIndex < fragments.length - 1) { fragmentIndex++; } } } } }