001: /*
002: * Copyright (c) 2001-2007, Jean Tessier
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * * Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * * Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in the
014: * documentation and/or other materials provided with the distribution.
015: *
016: * * Neither the name of Jean Tessier nor the names of his contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032:
033: package com.jeantessier.dependency;
034:
035: import java.util.*;
036:
037: import org.apache.log4j.*;
038: import org.apache.oro.text.perl.*;
039:
040: import com.jeantessier.text.*;
041:
042: public class RegularExpressionSelectionCriteria implements
043: SelectionCriteria {
044: private Perl5Util perl = new Perl5Util(
045: new MaximumCapacityPatternCache());
046:
047: private List<String> globalIncludes = new LinkedList<String>();
048: private List<String> globalExcludes = new LinkedList<String>();
049: private boolean matchingPackages = true;
050: private List<String> packageIncludes = new LinkedList<String>();
051: private List<String> packageExcludes = new LinkedList<String>();
052: private boolean matchingClasses = true;
053: private List<String> classIncludes = new LinkedList<String>();
054: private List<String> classExcludes = new LinkedList<String>();
055: private boolean matchingFeatures = true;
056: private List<String> featureIncludes = new LinkedList<String>();
057: private List<String> featureExcludes = new LinkedList<String>();
058:
059: public RegularExpressionSelectionCriteria() {
060: // Do nothing
061: }
062:
063: public RegularExpressionSelectionCriteria(
064: String initialGlobalIncludes) {
065: setGlobalIncludes(initialGlobalIncludes);
066: }
067:
068: public List<String> getGlobalIncludes() {
069: return globalIncludes;
070: }
071:
072: public void setGlobalIncludes(String globalIncludes) {
073: setGlobalIncludes(parseRE(globalIncludes));
074: }
075:
076: public void setGlobalIncludes(List<String> globalIncludes) {
077: this .globalIncludes = globalIncludes;
078: }
079:
080: public List<String> getGlobalExcludes() {
081: return globalExcludes;
082: }
083:
084: public void setGlobalExcludes(String globalExcludes) {
085: setGlobalExcludes(parseRE(globalExcludes));
086: }
087:
088: public void setGlobalExcludes(List<String> globalExcludes) {
089: this .globalExcludes = globalExcludes;
090: }
091:
092: public boolean isMatchingPackages() {
093: return matchingPackages;
094: }
095:
096: public void setMatchingPackages(boolean matchingPackages) {
097: this .matchingPackages = matchingPackages;
098: }
099:
100: public List<String> getPackageIncludes() {
101: return packageIncludes;
102: }
103:
104: public void setPackageIncludes(String packageIncludes) {
105: setPackageIncludes(parseRE(packageIncludes));
106: }
107:
108: public void setPackageIncludes(List<String> packageIncludes) {
109: this .packageIncludes = packageIncludes;
110: }
111:
112: public List<String> getPackageExcludes() {
113: return packageExcludes;
114: }
115:
116: public void setPackageExcludes(String packageExcludes) {
117: setPackageExcludes(parseRE(packageExcludes));
118: }
119:
120: public void setPackageExcludes(List<String> packageExcludes) {
121: this .packageExcludes = packageExcludes;
122: }
123:
124: public boolean isMatchingClasses() {
125: return matchingClasses;
126: }
127:
128: public void setMatchingClasses(boolean matchingClasses) {
129: this .matchingClasses = matchingClasses;
130: }
131:
132: public List<String> getClassIncludes() {
133: return classIncludes;
134: }
135:
136: public void setClassIncludes(String classIncludes) {
137: setClassIncludes(parseRE(classIncludes));
138: }
139:
140: public void setClassIncludes(List<String> classIncludes) {
141: this .classIncludes = classIncludes;
142: }
143:
144: public List<String> getClassExcludes() {
145: return classExcludes;
146: }
147:
148: public void setClassExcludes(String classExcludes) {
149: setClassExcludes(parseRE(classExcludes));
150: }
151:
152: public void setClassExcludes(List<String> classExcludes) {
153: this .classExcludes = classExcludes;
154: }
155:
156: public boolean isMatchingFeatures() {
157: return matchingFeatures;
158: }
159:
160: public void setMatchingFeatures(boolean matchingFeatures) {
161: this .matchingFeatures = matchingFeatures;
162: }
163:
164: public List<String> getFeatureIncludes() {
165: return featureIncludes;
166: }
167:
168: public void setFeatureIncludes(String featureIncludes) {
169: setFeatureIncludes(parseRE(featureIncludes));
170: }
171:
172: public void setFeatureIncludes(List<String> featureIncludes) {
173: this .featureIncludes = featureIncludes;
174: }
175:
176: public List<String> getFeatureExcludes() {
177: return featureExcludes;
178: }
179:
180: public void setFeatureExcludes(String featureExcludes) {
181: setFeatureExcludes(parseRE(featureExcludes));
182: }
183:
184: public void setFeatureExcludes(List<String> featureExcludes) {
185: this .featureExcludes = featureExcludes;
186: }
187:
188: public boolean matches(PackageNode node) {
189: return isMatchingPackages()
190: && matchesPackageName(node.getName());
191: }
192:
193: public boolean matches(ClassNode node) {
194: return isMatchingClasses() && matchesClassName(node.getName());
195: }
196:
197: public boolean matches(FeatureNode node) {
198: return isMatchingFeatures()
199: && matchesFeatureName(node.getName());
200: }
201:
202: public boolean matchesPackageName(String name) {
203: return matches(getGlobalIncludes(), getPackageIncludes(), name)
204: && !matches(getGlobalExcludes(), getPackageExcludes(),
205: name);
206: }
207:
208: public boolean matchesClassName(String name) {
209: return matches(getGlobalIncludes(), getClassIncludes(), name)
210: && !matches(getGlobalExcludes(), getClassExcludes(),
211: name);
212: }
213:
214: public boolean matchesFeatureName(String name) {
215: return matches(getGlobalIncludes(), getFeatureIncludes(), name)
216: && !matches(getGlobalExcludes(), getFeatureExcludes(),
217: name);
218: }
219:
220: private boolean matches(List<String> globalRegularExpressions,
221: List<String> regularExpressions, String name) {
222: boolean found = false;
223: Iterator<String> i;
224:
225: i = globalRegularExpressions.iterator();
226: while (!found && i.hasNext()) {
227: found = perl.match(i.next(), name);
228: }
229:
230: i = regularExpressions.iterator();
231: while (!found && i.hasNext()) {
232: found = perl.match(i.next(), name);
233: }
234:
235: return found;
236: }
237:
238: // Should be private, but left at package-level for the unit tests.
239: static List<String> parseRE(String re) {
240: List<String> result = new LinkedList<String>();
241:
242: Logger logger = Logger
243: .getLogger(RegularExpressionSelectionCriteria.class);
244: logger.debug("ParseRE \"" + re + "\"");
245:
246: int length = re.length();
247: int start = 0;
248: int stop = -1;
249:
250: while (start < length && stop < length) {
251: String separator = null;
252:
253: // Locate begining & determine separator
254: while (start < length && stop < start) {
255: if (re.charAt(start) == 'm' && (start + 1) < length) {
256: separator = re.substring(start + 1, start + 2);
257: stop = start + 2;
258: } else if (re.charAt(start) == '/') {
259: separator = "/";
260: stop = start + 1;
261: } else {
262: start++;
263: }
264: }
265:
266: logger.debug("start is " + start);
267: logger.debug("separator is " + separator);
268:
269: // Locate end
270: while (stop < length && start < stop) {
271: stop = re.indexOf(separator, stop);
272: logger.debug("indexOf() is " + stop);
273:
274: if (stop == -1 || re.charAt(stop - 1) != '\\') {
275:
276: if (stop == -1) {
277: stop = length;
278: } else {
279: // Look for modifiers
280: stop++;
281: while (stop < length
282: && (re.charAt(stop) == 'g'
283: || re.charAt(stop) == 'i'
284: || re.charAt(stop) == 'm'
285: || re.charAt(stop) == 'o'
286: || re.charAt(stop) == 's' || re
287: .charAt(stop) == 'x')) {
288: stop++;
289: }
290: }
291:
292: logger.debug("stop is " + stop);
293:
294: // Add candidate
295: logger.debug("candidate is \""
296: + re.substring(start, stop) + "\"");
297: result.add(re.substring(start, stop));
298:
299: // Move start
300: start = stop + 1;
301: } else {
302: stop++;
303: }
304: }
305: }
306:
307: return result;
308: }
309: }
|