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.joran.spi;
15  
16  import java.util.List;
17  
18  /**
19   * ElementSelector extends {@link ElementPath} with matching operations such as
20   * {@link #fullPathMatch(ElementPath)},
21   * {@link #getPrefixMatchLength(ElementPath)} and
22   * {@link #getTailMatchLength(ElementPath)}.
23   *
24   * <p>
25   * Parts of the path may contain '*' for wildcard matching.
26   *
27   * @author Ceki G&uuml;lc&uuml;
28   * @since 1.1.0
29   */
30  public class ElementSelector extends ElementPath {
31  
32      public ElementSelector() {
33          super();
34      }
35  
36      public ElementSelector(List<String> list) {
37          super(list);
38      }
39  
40      /**
41       * Build an elementPath from a string.
42       *
43       * Note that "/x" is considered equivalent to "x" and to "x/"
44       *
45       */
46      public ElementSelector(String p) {
47          super(p);
48      }
49  
50      public boolean fullPathMatch(ElementPath path) {
51          if (path.size() != size()) {
52              return false;
53          }
54  
55          int len = size();
56          for (int i = 0; i < len; i++) {
57              if (!equalityCheck(get(i), path.get(i))) {
58                  return false;
59              }
60          }
61          // if everything matches, then the two patterns are equal
62          return true;
63      }
64  
65      /**
66       * Returns the number of "tail" components that this pattern has in common with
67       * the pattern p passed as parameter. By "tail" components we mean the
68       * components at the end of the pattern.
69       */
70      public int getTailMatchLength(ElementPath p) {
71          if (p == null) {
72              return 0;
73          }
74  
75          int lSize = this.partList.size();
76          int rSize = p.partList.size();
77  
78          // no match possible for empty sets
79          if ((lSize == 0) || (rSize == 0)) {
80              return 0;
81          }
82  
83          int minLen = (lSize <= rSize) ? lSize : rSize;
84          int match = 0;
85  
86          // loop from the end to the front
87          for (int i = 1; i <= minLen; i++) {
88              String l = this.partList.get(lSize - i);
89              String r = p.partList.get(rSize - i);
90  
91              if (equalityCheck(l, r)) {
92                  match++;
93              } else {
94                  break;
95              }
96          }
97          return match;
98      }
99  
100     public boolean isContainedIn(ElementPath p) {
101         if (p == null) {
102             return false;
103         }
104         return p.toStableString().contains(toStableString());
105     }
106 
107     /**
108      * Returns the number of "prefix" components that this pattern has in common
109      * with the pattern p passed as parameter. By "prefix" components we mean the
110      * components at the beginning of the pattern.
111      */
112     public int getPrefixMatchLength(ElementPath p) {
113         if (p == null) {
114             return 0;
115         }
116 
117         int lSize = this.partList.size();
118         int rSize = p.partList.size();
119 
120         // no match possible for empty sets
121         if ((lSize == 0) || (rSize == 0)) {
122             return 0;
123         }
124 
125         int minLen = (lSize <= rSize) ? lSize : rSize;
126         int match = 0;
127 
128         for (int i = 0; i < minLen; i++) {
129             String l = this.partList.get(i);
130             String r = p.partList.get(i);
131 
132             if (equalityCheck(l, r)) {
133                 match++;
134             } else {
135                 break;
136             }
137         }
138 
139         return match;
140     }
141 
142     private boolean equalityCheck(String x, String y) {
143         return x.equalsIgnoreCase(y);
144     }
145 
146     @Override
147     public boolean equals(Object o) {
148         if ((o == null) || !(o instanceof ElementSelector)) {
149             return false;
150         }
151 
152         ElementSelector r = (ElementSelector) o;
153 
154         if (r.size() != size()) {
155             return false;
156         }
157 
158         int len = size();
159 
160         for (int i = 0; i < len; i++) {
161             if (!equalityCheck(get(i), r.get(i))) {
162                 return false;
163             }
164         }
165 
166         // if everything matches, then the two patterns are equal
167         return true;
168     }
169 
170     @Override
171     public int hashCode() {
172         int hc = 0;
173         int len = size();
174 
175         for (int i = 0; i < len; i++) {
176             // make Pattern comparisons case insensitive
177             // http://jira.qos.ch/browse/LBCORE-76
178             hc ^= get(i).toLowerCase().hashCode();
179         }
180         return hc;
181     }
182 
183 }