001 // Copyright 2004, 2005 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry.util;
016
017 import java.util.ArrayList;
018 import java.util.HashMap;
019 import java.util.List;
020 import java.util.Map;
021
022 import org.apache.hivemind.ApplicationRuntimeException;
023 import org.apache.oro.text.regex.MalformedPatternException;
024 import org.apache.oro.text.regex.MatchResult;
025 import org.apache.oro.text.regex.Pattern;
026 import org.apache.oro.text.regex.PatternCompiler;
027 import org.apache.oro.text.regex.PatternMatcher;
028 import org.apache.oro.text.regex.PatternMatcherInput;
029 import org.apache.oro.text.regex.Perl5Compiler;
030 import org.apache.oro.text.regex.Perl5Matcher;
031
032 /**
033 * Streamlines the interface to ORO by implicitly constructing the necessary compilers and matchers,
034 * and by caching compiled patterns.
035 *
036 * @author Howard Lewis Ship
037 * @since 3.0
038 */
039
040 public class RegexpMatcher
041 {
042 private PatternCompiler _patternCompiler;
043
044 private PatternMatcher _matcher;
045
046 private Map _compiledPatterns = new HashMap();
047
048 private Map _escapedPatternStrings = new HashMap();
049
050 protected Pattern compilePattern(String pattern)
051 {
052 if (_patternCompiler == null)
053 _patternCompiler = new Perl5Compiler();
054
055 try
056 {
057 return _patternCompiler.compile(pattern, Perl5Compiler.SINGLELINE_MASK | Perl5Compiler.READ_ONLY_MASK);
058 }
059 catch (MalformedPatternException ex)
060 {
061 throw new ApplicationRuntimeException(ex);
062 }
063 }
064
065 protected Pattern getCompiledPattern(String pattern)
066 {
067 Pattern result = (Pattern) _compiledPatterns.get(pattern);
068
069 if (result == null)
070 {
071 result = compilePattern(pattern);
072 _compiledPatterns.put(pattern, result);
073 }
074
075 return result;
076 }
077
078 /**
079 * Clears any previously compiled patterns.
080 */
081
082 public void clear()
083 {
084 _compiledPatterns.clear();
085 }
086
087 protected PatternMatcher getPatternMatcher()
088 {
089 if (_matcher == null)
090 _matcher = new Perl5Matcher();
091
092 return _matcher;
093 }
094
095 public boolean matches(String pattern, String input)
096 {
097 Pattern compiledPattern = getCompiledPattern(pattern);
098
099 return getPatternMatcher().matches(input, compiledPattern);
100 }
101
102 public boolean contains(String pattern, String input)
103 {
104 Pattern compiledPattern = getCompiledPattern(pattern);
105
106 return getPatternMatcher().contains(input, compiledPattern);
107 }
108
109 public String getEscapedPatternString(String pattern)
110 {
111 String result = (String) _escapedPatternStrings.get(pattern);
112
113 if (result == null)
114 {
115 result = Perl5Compiler.quotemeta(pattern);
116
117 _escapedPatternStrings.put(pattern, result);
118 }
119
120 return result;
121 }
122
123 /**
124 * Given an input string, finds all matches in an input string for the pattern.
125 *
126 * @param pattern
127 * the regexp pattern for matching
128 * @param input
129 * the string to search for matches within
130 * @return array (possibly empty) of matches
131 * @since 4.0
132 */
133 public RegexpMatch[] getMatches(String pattern, String input)
134 {
135 Pattern compiledPattern = getCompiledPattern(pattern);
136
137 PatternMatcher matcher = getPatternMatcher();
138 PatternMatcherInput matcherInput = new PatternMatcherInput(input);
139
140 List matches = new ArrayList();
141
142 while (matcher.contains(matcherInput, compiledPattern))
143 {
144 MatchResult match = matcher.getMatch();
145
146 matches.add(new RegexpMatch(match));
147 }
148
149 return (RegexpMatch[]) matches.toArray(new RegexpMatch[matches.size()]);
150 }
151
152 /**
153 * Given an input string, finds all matches in an input string for the pattern.
154 *
155 * @param pattern
156 * the regexp pattern for matching
157 * @param input
158 * the string to search for matches within
159 * @param subgroup
160 * the group (sub-expression) within the pattern to return as a match
161 * @return array (possibly empty) of matching strings
162 */
163 public String[] getMatches(String pattern, String input, int subgroup)
164 {
165 Pattern compiledPattern = getCompiledPattern(pattern);
166
167 PatternMatcher matcher = getPatternMatcher();
168 PatternMatcherInput matcherInput = new PatternMatcherInput(input);
169
170 List matches = new ArrayList();
171
172 while (matcher.contains(matcherInput, compiledPattern))
173 {
174 MatchResult match = matcher.getMatch();
175
176 String matchedInput = match.group(subgroup);
177
178 matches.add(matchedInput);
179 }
180
181 return (String[]) matches.toArray(new String[matches.size()]);
182 }
183
184 }