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 TargetLengthBasedClassNameAbbreviator implements Abbreviator {
20
21     final int targetLength;
22
23     public TargetLengthBasedClassNameAbbreviator(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/LBCLASSIC-110
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 not dots than abbreviation is not possible
48         if (dotCount == 0) {
49             return fqClassName;
50         }
51         // printArray("dotArray: ", dotArray);
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     static int computeDotIndexes(final String className, int[] dotArray) {
67         int dotCount = 0;
68         int k = 0;
69         while (true) {
70             // ignore the $ separator in our computations. This is both convenient
71             // and sensible.
72             k = className.indexOf(CoreConstants.DOT, k);
73             if (k != -1 && dotCount < ClassicConstants.MAX_DOTS) {
74                 dotArray[dotCount] = k;
75                 dotCount++;
76                 k++;
77             } else {
78                 break;
79             }
80         }
81         return dotCount;
82     }
83
84     void computeLengthArray(final String className, int[] dotArray, int[] lengthArray, int dotCount) {
85         int toTrim = className.length() - targetLength;
86         // System.out.println("toTrim=" + toTrim);
87
88         // int toTrimAvarage = 0;
89
90         int len;
91         for (int i = 0; i < dotCount; i++) {
92             int previousDotPosition = -1;
93             if (i > 0) {
94                 previousDotPosition = dotArray[i - 1];
95             }
96             int available = dotArray[i] - previousDotPosition - 1;
97             // System.out.println("i=" + i + ", available = " + available);
98
99             len = (available < 1) ? available : 1;
100             // System.out.println("i=" + i + ", toTrim = " + toTrim);
101
102             if (toTrim > 0) {
103                 len = (available < 1) ? available : 1;
104             } else {
105                 len = available;
106             }
107             toTrim -= (available - len);
108             lengthArray[i] = len + 1;
109         }
110
111         int lastDotIndex = dotCount - 1;
112         lengthArray[dotCount] = className.length() - dotArray[lastDotIndex];
113     }
114
115     static void printArray(String msg, int[] ia) {
116         System.out.print(msg);
117         for (int i = 0; i < ia.length; i++) {
118             if (i == 0) {
119                 System.out.print(ia[i]);
120             } else {
121                 System.out.print(", " + ia[i]);
122             }
123         }
124         System.out.println();
125     }
126 }