Remove System.out.println from RevWalkFilterTest
[egit/chris.git] / org.spearce.jgit / src / org / spearce / jgit / fnmatch / GroupHead.java
blob9f72010b73dc5efbbe1ba17e23d5a415bb421489
1 /*
2 * Copyright (C) 2008, Florian Köberle <florianskarten@web.de>
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
8 * conditions are met:
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * - Neither the name of the Git Development Community nor the
19 * names of its contributors may be used to endorse or promote
20 * products derived from this software without specific prior
21 * written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 package org.spearce.jgit.fnmatch;
40 import java.util.ArrayList;
41 import java.util.List;
42 import java.util.regex.Matcher;
43 import java.util.regex.Pattern;
45 import org.spearce.jgit.errors.InvalidPatternException;
47 final class GroupHead extends AbstractHead {
48 private final List<CharacterPattern> characterClasses;
50 private static final Pattern REGEX_PATTERN = Pattern
51 .compile("([^-][-][^-]|\\[[.:=].*?[.:=]\\])");
53 private final boolean inverse;
55 GroupHead(String pattern, final String wholePattern)
56 throws InvalidPatternException {
57 super(false);
58 this.characterClasses = new ArrayList<CharacterPattern>();
59 this.inverse = pattern.startsWith("!");
60 if (inverse) {
61 pattern = pattern.substring(1);
63 final Matcher matcher = REGEX_PATTERN.matcher(pattern);
64 while (matcher.find()) {
65 final String characterClass = matcher.group(0);
66 if (characterClass.length() == 3 && characterClass.charAt(1) == '-') {
67 final char start = characterClass.charAt(0);
68 final char end = characterClass.charAt(2);
69 characterClasses.add(new CharacterRange(start, end));
70 } else if (characterClass.equals("[:alnum:]")) {
71 characterClasses.add(LetterPattern.INSTANCE);
72 characterClasses.add(DigitPattern.INSTANCE);
73 } else if (characterClass.equals("[:alpha:]")) {
74 characterClasses.add(LetterPattern.INSTANCE);
75 } else if (characterClass.equals("[:blank:]")) {
76 characterClasses.add(new OneCharacterPattern(' '));
77 characterClasses.add(new OneCharacterPattern('\t'));
78 } else if (characterClass.equals("[:cntrl:]")) {
79 characterClasses.add(new CharacterRange('\u0000', '\u001F'));
80 characterClasses.add(new OneCharacterPattern('\u007F'));
81 } else if (characterClass.equals("[:digit:]")) {
82 characterClasses.add(DigitPattern.INSTANCE);
83 } else if (characterClass.equals("[:graph:]")) {
84 characterClasses.add(new CharacterRange('\u0021', '\u007E'));
85 characterClasses.add(LetterPattern.INSTANCE);
86 characterClasses.add(DigitPattern.INSTANCE);
87 } else if (characterClass.equals("[:lower:]")) {
88 characterClasses.add(LowerPattern.INSTANCE);
89 } else if (characterClass.equals("[:print:]")) {
90 characterClasses.add(new CharacterRange('\u0020', '\u007E'));
91 characterClasses.add(LetterPattern.INSTANCE);
92 characterClasses.add(DigitPattern.INSTANCE);
93 } else if (characterClass.equals("[:punct:]")) {
94 characterClasses.add(PunctPattern.INSTANCE);
95 } else if (characterClass.equals("[:space:]")) {
96 characterClasses.add(WhitespacePattern.INSTANCE);
97 } else if (characterClass.equals("[:upper:]")) {
98 characterClasses.add(UpperPattern.INSTANCE);
99 } else if (characterClass.equals("[:xdigit:]")) {
100 characterClasses.add(new CharacterRange('0', '9'));
101 characterClasses.add(new CharacterRange('a', 'f'));
102 characterClasses.add(new CharacterRange('A', 'F'));
103 } else if (characterClass.equals("[:word:]")) {
104 characterClasses.add(new OneCharacterPattern('_'));
105 characterClasses.add(LetterPattern.INSTANCE);
106 characterClasses.add(DigitPattern.INSTANCE);
107 } else {
108 final String message = String.format(
109 "The character class %s is not supported.",
110 characterClass);
111 throw new InvalidPatternException(message, wholePattern);
114 pattern = matcher.replaceFirst("");
115 matcher.reset(pattern);
117 // pattern contains now no ranges
118 for (int i = 0; i < pattern.length(); i++) {
119 final char c = pattern.charAt(i);
120 characterClasses.add(new OneCharacterPattern(c));
124 @Override
125 protected final boolean matches(final char c) {
126 for (CharacterPattern pattern : characterClasses) {
127 if (pattern.matches(c)) {
128 return !inverse;
131 return inverse;
134 private interface CharacterPattern {
136 * @param c
137 * the character to test
138 * @return returns true if the character matches a pattern.
140 boolean matches(char c);
143 private static final class CharacterRange implements CharacterPattern {
144 private final char start;
146 private final char end;
148 CharacterRange(char start, char end) {
149 this.start = start;
150 this.end = end;
153 public final boolean matches(char c) {
154 return start <= c && c <= end;
158 private static final class DigitPattern implements CharacterPattern {
159 static final GroupHead.DigitPattern INSTANCE = new DigitPattern();
161 public final boolean matches(char c) {
162 return Character.isDigit(c);
166 private static final class LetterPattern implements CharacterPattern {
167 static final GroupHead.LetterPattern INSTANCE = new LetterPattern();
169 public final boolean matches(char c) {
170 return Character.isLetter(c);
174 private static final class LowerPattern implements CharacterPattern {
175 static final GroupHead.LowerPattern INSTANCE = new LowerPattern();
177 public final boolean matches(char c) {
178 return Character.isLowerCase(c);
182 private static final class UpperPattern implements CharacterPattern {
183 static final GroupHead.UpperPattern INSTANCE = new UpperPattern();
185 public final boolean matches(char c) {
186 return Character.isUpperCase(c);
190 private static final class WhitespacePattern implements CharacterPattern {
191 static final GroupHead.WhitespacePattern INSTANCE = new WhitespacePattern();
193 public final boolean matches(char c) {
194 return Character.isWhitespace(c);
198 private static final class OneCharacterPattern implements CharacterPattern {
199 private char expectedCharacter;
201 OneCharacterPattern(final char c) {
202 this.expectedCharacter = c;
205 public final boolean matches(char c) {
206 return this.expectedCharacter == c;
210 private static final class PunctPattern implements CharacterPattern {
211 static final GroupHead.PunctPattern INSTANCE = new PunctPattern();
213 private static String punctCharacters = "-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~";
215 public boolean matches(char c) {
216 return punctCharacters.indexOf(c) != -1;