View Javadoc

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