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 ch.qos.logback.classic.ClassicConstants; 017import ch.qos.logback.core.CoreConstants; 018 019public class TargetLengthBasedClassNameAbbreviator2 implements Abbreviator { 020 021 final int targetLength; 022 023 public TargetLengthBasedClassNameAbbreviator2(int targetLength) { 024 this.targetLength = targetLength; 025 } 026 027 public String abbreviate(String fqClassName) { 028 StringBuilder buf = new StringBuilder(targetLength); 029 if (fqClassName == null) { 030 throw new IllegalArgumentException("Class name may not be null"); 031 } 032 033 int inLen = fqClassName.length(); 034 if (inLen < targetLength) { 035 return fqClassName; 036 } 037 038 int[] dotIndexesArray = new int[ClassicConstants.MAX_DOTS]; 039 // a.b.c contains 2 dots but 2+1 parts. 040 // see also http://jira.qos.ch/browse/LOGBACK-437 041 int[] lengthArray = new int[ClassicConstants.MAX_DOTS + 1]; 042 043 int dotCount = computeDotIndexes(fqClassName, dotIndexesArray); 044 045 // System.out.println(); 046 // System.out.println("Dot count for [" + className + "] is " + dotCount); 047 // if there are no dots than abbreviation is not possible 048 if (dotCount == 0) { 049 return fqClassName; 050 } 051 // printArray("dotArray: ", dotIndexesArray); 052 computeLengthArray(fqClassName, dotIndexesArray, lengthArray, dotCount); 053 // printArray("lengthArray: ", lengthArray); 054 for (int i = 0; i <= dotCount; i++) { 055 if (i == 0) { 056 buf.append(fqClassName.substring(0, lengthArray[i] - 1)); 057 } else { 058 buf.append(fqClassName.substring(dotIndexesArray[i - 1], dotIndexesArray[i - 1] + lengthArray[i])); 059 } 060 // System.out.println("i=" + i + ", buf=" + buf); 061 } 062 063 return buf.toString(); 064 } 065 066 /** 067 * Populate dotArray with the positions of the DOT character in className. 068 * Leftmost dot is placed at index 0 of dotArray. 069 * 070 * @param className 071 * @param dotArray 072 * @return the number of dots found 073 */ 074 static int computeDotIndexes(final String className, int[] dotArray) { 075 int dotCount = 0; 076 int k = 0; 077 while (true) { 078 // ignore the $ separator in our computations. This is both convenient 079 // and sensible. 080 k = className.indexOf(CoreConstants.DOT, k); 081 if (k != -1 && dotCount < ClassicConstants.MAX_DOTS) { 082 dotArray[dotCount] = k; 083 dotCount++; 084 k++; // move past the last found DOT 085 } else { 086 break; 087 } 088 } 089 return dotCount; 090 } 091 092 void computeLengthArray(final String className, int[] dotArray, int[] lengthArray, int dotCount) { 093 int toTrim = className.length() - targetLength; 094 // System.out.println("dotCount=" + dotCount); 095 096 int len; 097 for (int i = 0; i < dotCount; i++) { 098 // System.out.println("i=" + i + ", toTrim = " + toTrim); 099 100 // if i==0, previousDotPosition = -1, otherwise dotArray[i - 1] 101 int previousDotPosition = (i == 0) ? -1 : dotArray[i - 1]; 102 // System.out.println("i="+i+ " previousDotPosition="+previousDotPosition); 103 104 // number of characters within the segment, i.e/ within the previous dot 105 // position and the current dot position 106 int charactersInSegment = dotArray[i] - previousDotPosition - 1; 107 // System.out.println("i=" + i + ", charactersInSegment = " + 108 // charactersInSegment); 109 110 if (toTrim > 0) { 111 len = (charactersInSegment < 1) ? charactersInSegment : 1; 112 } else { 113 len = charactersInSegment; 114 } 115 // System.out.println("i=" + i + ", len = " + len); 116 117 toTrim -= (charactersInSegment - len); 118 lengthArray[i] = len + 1; 119 } 120 121 int lastDotIndex = dotCount - 1; 122 lengthArray[dotCount] = className.length() - dotArray[lastDotIndex]; 123 } 124 125 static void printArray(String msg, int[] ia) { 126 System.out.print(msg); 127 for (int i = 0; i < ia.length; i++) { 128 if (i == 0) { 129 System.out.print(ia[i]); 130 } else { 131 System.out.print(", " + ia[i]); 132 } 133 } 134 System.out.println(); 135 } 136}