1 20 21 package net.innig.macker.rule; 22 23 import java.util.*; 24 25 import org.apache.regexp.RE; 26 import org.apache.regexp.RESyntaxException; 27 28 public final class MackerRegex 29 { 30 34 public MackerRegex(String regexStr) 35 throws MackerRegexSyntaxException 36 { this(regexStr, true); } 37 38 public MackerRegex(String regexStr, boolean allowParts) 39 throws MackerRegexSyntaxException 40 { 41 if(regexStr == null) 42 throw new NullPointerException ("regexStr == null"); 43 buildStaticPatterns(); 44 45 this.regexStr = regexStr; 46 parts = null; 47 regex = null; 48 prevVarValues = new HashMap(); 49 50 if(!(allowParts ? allowable : allowableNoParts).match(regexStr)) 51 throw new MackerRegexSyntaxException(regexStr); 52 } 53 54 58 public String getPatternString() 59 { return regexStr; } 60 61 private final String regexStr; 62 63 67 public boolean matches(EvaluationContext context, String s) 68 throws UndeclaredVariableException, MackerRegexSyntaxException 69 { return getMatch(context, s) != null; } 70 71 public String getMatch(EvaluationContext context, String s) 72 throws UndeclaredVariableException, MackerRegexSyntaxException 73 { 74 parseExpr(context); 75 Boolean match = (Boolean ) matchCache.get(s); 76 if(Boolean.FALSE.equals(match)) 77 return null; 78 if(Boolean.TRUE.equals(match)) 79 return (String ) matchResultCache.get(s); 80 81 match = regex.match('.' + s) ? Boolean.TRUE : Boolean.FALSE; 82 matchCache.put(s, match); 83 if(match.booleanValue()) 84 { 85 String matchResult = regex.getParen(regex.getParenCount() - 1); 86 matchResultCache.put(s, matchResult); 87 return matchResult; 88 } 89 else 90 return null; 91 } 92 93 private void parseExpr(EvaluationContext context) 94 throws UndeclaredVariableException, MackerRegexSyntaxException 95 { 96 buildStaticPatterns(); 97 98 if(parts == null) 99 { 100 parts = new ArrayList(); 101 for(int pos = 0; pos >= 0; ) 102 { 103 boolean hasAnotherVar = var.match(regexStr, pos); 104 int expEnd = hasAnotherVar ? var.getParenStart(0) : regexStr.length(); 105 106 if(pos < expEnd) 107 parts.add(new ExpPart(parseSubexpr(regexStr.substring(pos, expEnd)))); 108 if(hasAnotherVar) 109 parts.add(new VarPart(var.getParen(1))); 110 111 pos = hasAnotherVar ? var.getParenEnd(0) : -1; 112 } 113 } 114 115 118 boolean changed = (regex == null); 119 for(Iterator i = prevVarValues.entrySet().iterator(); !changed && i.hasNext(); ) 120 { 121 Map.Entry entry = (Map.Entry) i.next(); 122 String name = (String ) entry.getKey(); 123 String value = (String ) entry.getValue(); 124 if(!context.getVariableValue(name).equals(value)) 125 changed = true; 126 } 127 128 if(changed) 129 { 130 StringBuffer builtRegexStr = new StringBuffer ("^\\.?"); 131 for(Iterator i = parts.iterator(); i.hasNext(); ) 132 { 133 Part part = (Part) i.next(); 134 if(part instanceof VarPart) 135 { 136 String varName = ((VarPart) part).varName; 137 String varValue = context.getVariableValue(varName); 138 prevVarValues.put(varName, varValue); 139 builtRegexStr.append( 140 parseSubexpr(varValue)); 141 } 142 else if(part instanceof ExpPart) 143 builtRegexStr.append( 144 ((ExpPart) part).exp); 145 } 146 builtRegexStr.append('$'); 147 148 try { regex = new RE(builtRegexStr.toString()); } 149 catch(RESyntaxException rese) 150 { 151 System.out.println("builtRegexStr = " + builtRegexStr); 152 throw new MackerRegexSyntaxException(regexStr, rese); 153 } 154 155 matchCache = new HashMap(); 158 matchResultCache = new HashMap(); 159 } 160 } 161 162 private String parseSubexpr(String exp) 163 { 164 exp = partBoundary.subst(exp, "[\\.\\$]"); 165 exp = packageBoundary.subst(exp, "\\."); 166 exp = innerClassBoundary.subst(exp, "\\$"); 167 exp = star.subst(exp, "@"); 168 exp = matchAcross.subst(exp, ".*"); 169 exp = matchWithin.subst(exp, "[^\\.]*"); 170 return exp; 172 } 173 174 private static void buildStaticPatterns() 175 { 176 if(allowable == null) 177 try { 178 star = new RE("\\*"); 179 matchWithin = new RE("@"); 180 matchAcross = new RE("@@"); 181 partBoundary = new RE("\\."); 182 packageBoundary = new RE("/"); 183 innerClassBoundary = new RE("\\$"); 184 185 String varS = "\\$\\{([A-Za-z0-9_\\.\\-]+)\\}"; 186 String partS = "(([A-Za-z_]|[\\(\\)]|\\*|" + varS + ")" 187 + "([A-Za-z0-9_]|[\\(\\)]|\\*|" + varS + ")*)"; 188 var = new RE(varS); 189 allowable = new RE("^([\\$\\./]?" + partS + ")+$", RE.MATCH_SINGLELINE); 190 allowableNoParts = new RE("^" + partS + "$", RE.MATCH_SINGLELINE); 191 } 192 catch(RESyntaxException rese) 193 { 194 rese.printStackTrace(System.out); 195 throw new RuntimeException ("Can't initialize RegexPattern: " + rese); 196 } 197 } 198 199 private RE regex; 200 private List parts; 201 private Map prevVarValues, matchCache, matchResultCache; 202 static private RE star, matchWithin, matchAcross, 203 partBoundary, packageBoundary, innerClassBoundary, var, 204 allowable, allowableNoParts; 205 206 private class Part { } 207 private class VarPart extends Part 208 { 209 public VarPart(String varName) { this.varName = varName; } 210 public String varName; 211 public String toString() { return "var(" + varName + ")"; } 212 } 213 private class ExpPart extends Part 214 { 215 public ExpPart(String exp) { this.exp = exp; } 216 public String exp; 217 public String toString() { return "exp(" + exp + ")"; } 218 } 219 220 224 public String toString() 225 { return '"' + regexStr + '"'; } 226 } 227 228 | Popular Tags |