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.core.util;
15  
16  import java.text.DateFormatSymbols;
17  
18  /**
19   * This class supports mapping character sequences to
20   * regular expressions as appropriate for SimpleDateFormatter.
21   *
22   * @author Ceki
23   */
24  class CharSequenceToRegexMapper {
25  
26      DateFormatSymbols symbols = DateFormatSymbols.getInstance();
27  
28      String toRegex(CharSequenceState css) {
29          final int occurrences = css.occurrences;
30          final char c = css.c;
31          switch (css.c) {
32          case 'G':
33          case 'z':
34              return ".*";
35          case 'M':
36              if (occurrences <= 2)
37                  return number(occurrences);
38              else if (occurrences == 3)
39                  return getRegexForShortMonths();
40              else
41                  return getRegexForLongMonths();
42          case 'y':
43          case 'w':
44          case 'W':
45          case 'D':
46          case 'd':
47          case 'F':
48          case 'H':
49          case 'k':
50          case 'K':
51          case 'h':
52          case 'm':
53          case 's':
54          case 'S':
55              return number(occurrences);
56          case 'E':
57              if (occurrences >= 4) {
58                  return getRegexForLongDaysOfTheWeek();
59              } else {
60                  return getRegexForShortDaysOfTheWeek();
61              }
62          case 'a':
63              return getRegexForAmPms();
64          case 'Z':
65              return "(\\+|-)\\d{4}";
66          case '.':
67              return "\\.";
68          case '\\':
69              throw new IllegalStateException("Forward slashes are not allowed");
70          case '\'':
71              if (occurrences == 1) {
72                  return "";
73              }
74              throw new IllegalStateException("Too many single quotes");
75          default:
76              if (occurrences == 1) {
77                  return "" + c;
78              } else {
79                  return c + "{" + occurrences + "}";
80              }
81          }
82      }
83  
84      private String number(int occurrences) {
85          return "\\d{" + occurrences + "}";
86      }
87  
88      private String getRegexForAmPms() {
89          return symbolArrayToRegex(symbols.getAmPmStrings());
90      }
91  
92      private String getRegexForLongDaysOfTheWeek() {
93          return symbolArrayToRegex(symbols.getWeekdays());
94      }
95  
96      private String getRegexForShortDaysOfTheWeek() {
97          return symbolArrayToRegex(symbols.getShortWeekdays());
98      }
99  
100     private String getRegexForLongMonths() {
101         return symbolArrayToRegex(symbols.getMonths());
102     }
103 
104     String getRegexForShortMonths() {
105         return symbolArrayToRegex(symbols.getShortMonths());
106     }
107 
108     private String symbolArrayToRegex(String[] symbolArray) {
109         int[] minMax = findMinMaxLengthsInSymbols(symbolArray);
110         return ".{" + minMax[0] + "," + minMax[1] + "}";
111     }
112 
113     static int[] findMinMaxLengthsInSymbols(String[] symbols) {
114         int min = Integer.MAX_VALUE;
115         int max = 0;
116         for (String symbol : symbols) {
117             int len = symbol.length();
118             // some SENTINEL values can be empty strings, the month at index 12 or the weekday at index 0
119             if (len == 0)
120                 continue;
121             min = Math.min(min, len);
122             max = Math.max(max, len);
123         }
124         return new int[] { min, max };
125     }
126 }