View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2009, 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.joran.spi;
15  
16  import java.util.ArrayList;
17  import java.util.List;
18  
19  /**
20   * A pattern is used to designate XML elements in a document.
21   * 
22   * <p>For more information see
23   * http://logback.qos.ch/manual/onJoran.html#pattern
24   * 
25   * @author Ceki G&uuml;lc&uuml;
26   */
27  public class Pattern {
28  
29    // contains String instances
30    ArrayList<String> partList = new ArrayList<String>();
31  
32  
33    public Pattern() {
34    }
35  
36    public Pattern(List<String> list) {
37      partList.addAll(list);
38    }
39  
40    /**
41     * Build a pattern from a string.
42     * 
43     * Note that "/x" is considered equivalent to "x" and to "x/"
44     * 
45     */
46    public Pattern(String p) {
47      this();
48  
49      if (p == null) {
50        return;
51      }
52  
53      int lastIndex = 0;
54  
55      // System.out.println("p is "+ p);
56      while (true) {
57        int k = p.indexOf('/', lastIndex);
58  
59        // System.out.println("k is "+ k);
60        if (k == -1) {
61          String lastPart = p.substring(lastIndex);
62          if (lastPart != null && lastPart.length() > 0) {
63            partList.add(p.substring(lastIndex));
64          }
65          break;
66        } else {
67          String c = p.substring(lastIndex, k);
68  
69          if (c.length() > 0) {
70            partList.add(c);
71          }
72  
73          lastIndex = k + 1;
74        }
75      }
76  
77      // System.out.println(components);
78    }
79  
80    public List<String> getCopyOfPartList() {
81      return new ArrayList<String>(partList);
82    }
83    
84    public Object clone() {
85      Pattern p = new Pattern();
86      p.partList.addAll(this.partList);
87      return p;
88    }
89  
90    public void push(String s) {
91      partList.add(s);
92    }
93  
94    public int size() {
95      return partList.size();
96    }
97  
98    public String get(int i) {
99      return (String) partList.get(i);
100   }
101 
102   public void pop() {
103     if (!partList.isEmpty()) {
104       partList.remove(partList.size() - 1);
105     }
106   }
107 
108   public String peekLast() {
109     if (!partList.isEmpty()) {
110       int size = partList.size();
111       return (String) partList.get(size - 1);
112     } else {
113       return null;
114     }
115   }
116 
117   /**
118    * Returns the number of "tail" components that this pattern has in common
119    * with the pattern p passed as parameter. By "tail" components we mean the
120    * components at the end of the pattern.
121    */
122   public int getTailMatchLength(Pattern p) {
123     if (p == null) {
124       return 0;
125     }
126 
127     int lSize = this.partList.size();
128     int rSize = p.partList.size();
129 
130     // no match possible for empty sets
131     if ((lSize == 0) || (rSize == 0)) {
132       return 0;
133     }
134 
135     int minLen = (lSize <= rSize) ? lSize : rSize;
136     int match = 0;
137 
138     // loop from the end to the front
139     for (int i = 1; i <= minLen; i++) {
140       String l = (String) this.partList.get(lSize - i);
141       String r = (String) p.partList.get(rSize - i);
142 
143       if (equalityCheck(l, r)) {
144         match++;
145       } else {
146         break;
147       }
148     }
149     return match;
150   }
151 
152   public boolean isContained(Pattern p) {
153     if(p == null) {
154       return false;
155     }
156     String lStr = this.toString();
157     return lStr.contains(p.toString());
158   }
159   
160   
161   /**
162    * Returns the number of "prefix" components that this pattern has in common
163    * with the pattern p passed as parameter. By "prefix" components we mean the
164    * components at the beginning of the pattern.
165    */
166   public int getPrefixMatchLength(Pattern p) {
167     if (p == null) {
168       return 0;
169     }
170 
171     int lSize = this.partList.size();
172     int rSize = p.partList.size();
173 
174     // no match possible for empty sets
175     if ((lSize == 0) || (rSize == 0)) {
176       return 0;
177     }
178 
179     int minLen = (lSize <= rSize) ? lSize : rSize;
180     int match = 0;
181 
182     for (int i = 0; i < minLen; i++) {
183       String l = (String) this.partList.get(i);
184       String r = (String) p.partList.get(i);
185 
186       if (equalityCheck(l, r)) {
187         match++;
188       } else {
189         break;
190       }
191     }
192 
193     return match;
194   }
195 
196   private boolean equalityCheck(String x, String y) {
197     return x.equalsIgnoreCase(y);
198   }
199 
200   @Override
201   public boolean equals(Object o) {
202     if ((o == null) || !(o instanceof Pattern)) {
203       return false;
204     }
205 
206     Pattern r = (Pattern) o;
207 
208     if (r.size() != size()) {
209       return false;
210     }
211 
212     int len = size();
213 
214     for (int i = 0; i < len; i++) {
215       if (!equalityCheck(get(i), r.get(i))) {
216         return false;
217       }
218     }
219 
220     // if everything matches, then the two patterns are equal
221     return true;
222   }
223 
224   @Override
225   public int hashCode() {
226     int hc = 0;
227     int len = size();
228 
229     for (int i = 0; i < len; i++) {
230       // make Pattern comparisons case insensitive
231       // http://jira.qos.ch/browse/LBCORE-76
232       hc ^= get(i).toLowerCase().hashCode();
233     }
234 
235     return hc;
236   }
237 
238   @Override
239   public String toString() {
240     int size = partList.size();
241     String result = "";
242     for (int i = 0; i < size; i++) {
243       result += "[" + partList.get(i) + "]";
244     }
245     return result;
246   }
247 }