001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.classic.pattern; 015 016import static ch.qos.logback.core.CoreConstants.DOT; 017 018public class TargetLengthBasedClassNameAbbreviator implements Abbreviator { 019 020 final int targetLength; 021 022 public TargetLengthBasedClassNameAbbreviator(int targetLength) { 023 this.targetLength = targetLength; 024 } 025 026 public String abbreviate(String fqClassName) { 027 if (fqClassName == null) { 028 throw new IllegalArgumentException("Class name may not be null"); 029 } 030 031 int inLen = fqClassName.length(); 032 if (inLen < targetLength) { 033 return fqClassName; 034 } 035 036 StringBuilder buf = new StringBuilder(inLen); 037 038 int rightMostDotIndex = fqClassName.lastIndexOf(DOT); 039 040 if (rightMostDotIndex == -1) 041 return fqClassName; 042 043 // length of last segment including the dot 044 int lastSegmentLength = inLen - rightMostDotIndex; 045 046 int leftSegments_TargetLen = targetLength - lastSegmentLength; 047 if (leftSegments_TargetLen < 0) 048 leftSegments_TargetLen = 0; 049 050 int leftSegmentsLen = inLen - lastSegmentLength; 051 052 // maxPossibleTrim denotes the maximum number of characters we aim to trim 053 // the actual number of character trimmed may be higher since segments, when 054 // reduced, are reduced to just one character 055 int maxPossibleTrim = leftSegmentsLen - leftSegments_TargetLen; 056 057 int trimmed = 0; 058 boolean inDotState = true; 059 060 int i = 0; 061 for (; i < rightMostDotIndex; i++) { 062 char c = fqClassName.charAt(i); 063 if (c == DOT) { 064 // if trimmed too many characters, let us stop 065 if (trimmed >= maxPossibleTrim) 066 break; 067 buf.append(c); 068 inDotState = true; 069 } else { 070 if (inDotState) { 071 buf.append(c); 072 inDotState = false; 073 } else { 074 trimmed++; 075 } 076 } 077 } 078 // append from the position of i which may include the last seen DOT 079 buf.append(fqClassName.substring(i)); 080 return buf.toString(); 081 } 082}