View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.pattern;
15  
16  import ch.qos.logback.classic.ClassicConstants;
17  import ch.qos.logback.core.CoreConstants;
18  
19  public class TargetLengthBasedClassNameAbbreviator2 implements Abbreviator {
20  
21      final int targetLength;
22  
23      public TargetLengthBasedClassNameAbbreviator2(int targetLength) {
24          this.targetLength = targetLength;
25      }
26  
27      public String abbreviate(String fqClassName) {
28          StringBuilder buf = new StringBuilder(targetLength);
29          if (fqClassName == null) {
30              throw new IllegalArgumentException("Class name may not be null");
31          }
32  
33          int inLen = fqClassName.length();
34          if (inLen < targetLength) {
35              return fqClassName;
36          }
37  
38          int[] dotIndexesArray = new int[ClassicConstants.MAX_DOTS];
39          // a.b.c contains 2 dots but 2+1 parts.
40          // see also http://jira.qos.ch/browse/LOGBACK-437
41          int[] lengthArray = new int[ClassicConstants.MAX_DOTS + 1];
42  
43          int dotCount = computeDotIndexes(fqClassName, dotIndexesArray);
44  
45          // System.out.println();
46          // System.out.println("Dot count for [" + className + "] is " + dotCount);
47          // if there are no dots than abbreviation is not possible
48          if (dotCount == 0) {
49              return fqClassName;
50          }
51          // printArray("dotArray: ", dotIndexesArray);
52          computeLengthArray(fqClassName, dotIndexesArray, lengthArray, dotCount);
53          // printArray("lengthArray: ", lengthArray);
54          for (int i = 0; i <= dotCount; i++) {
55              if (i == 0) {
56                  buf.append(fqClassName.substring(0, lengthArray[i] - 1));
57              } else {
58                  buf.append(fqClassName.substring(dotIndexesArray[i - 1], dotIndexesArray[i - 1] + lengthArray[i]));
59              }
60              // System.out.println("i=" + i + ", buf=" + buf);
61          }
62  
63          return buf.toString();
64      }
65  
66      /**
67       * Populate dotArray with the positions of the DOT character in className.
68       * Leftmost dot is placed at index 0 of dotArray.
69       * 
70       * @param className
71       * @param dotArray
72       * @return the number of dots found
73       */
74      static int computeDotIndexes(final String className, int[] dotArray) {
75          int dotCount = 0;
76          int k = 0;
77          while (true) {
78              // ignore the $ separator in our computations. This is both convenient
79              // and sensible.
80              k = className.indexOf(CoreConstants.DOT, k);
81              if (k != -1 && dotCount < ClassicConstants.MAX_DOTS) {
82                  dotArray[dotCount] = k;
83                  dotCount++;
84                  k++; // move past the last found DOT
85              } else {
86                  break;
87              }
88          }
89          return dotCount;
90      }
91  
92      void computeLengthArray(final String className, int[] dotArray, int[] lengthArray, int dotCount) {
93          int toTrim = className.length() - targetLength;
94          // System.out.println("dotCount=" + dotCount);
95  
96          int len;
97          for (int i = 0; i < dotCount; i++) {
98              // System.out.println("i=" + i + ", toTrim = " + toTrim);
99  
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 }