1 16 package org.apache.cocoon.components.treeprocessor; 17 18 import java.util.ArrayList ; 19 import java.util.Collections ; 20 import java.util.HashMap ; 21 import java.util.Iterator ; 22 import java.util.List ; 23 import java.util.Map ; 24 25 import org.apache.avalon.framework.parameters.Parameters; 26 import org.apache.cocoon.sitemap.PatternException; 27 28 35 36 public abstract class MapStackResolver { 37 38 public static final Map EMPTY_MAP = Collections.unmodifiableMap(new java.util.HashMap (0)); 39 40 43 public abstract String resolve(List mapStack) throws PatternException; 44 45 48 public static boolean needsResolve(String expression) { 49 if (expression == null || expression.length() == 0) { 50 return false; 51 } 52 53 if (expression.charAt(0) == '{') { 55 return true; 56 } 57 58 if (expression.length() < 2) { 59 return false; 60 } 61 62 int pos = 1; 64 while ( (pos = expression.indexOf('{', pos)) != -1) { 65 if (expression.charAt(pos - 1) != '\\') { 67 return true; 69 } 70 pos++; 71 } 72 return false; 74 } 75 76 83 public static String unescape(String expression) { 84 if (expression == null || expression.indexOf("\\{") == -1) { 86 return expression; 87 } 88 89 StringBuffer buf = new StringBuffer (); 90 for (int i = 0; i < expression.length(); i++) { 91 char ch = expression.charAt(i); 92 if (ch != '\\' || i >= (expression.length() - 1) || expression.charAt(i+1) != '{') { 93 buf.append(ch); 94 } 95 } 96 97 return buf.toString(); 98 } 99 100 104 public static MapStackResolver getResolver(String expression) throws PatternException { 105 if (needsResolve(expression)) { 106 return new CompiledResolver(expression); 108 } else { 109 return new NullResolver(expression); 110 } 111 } 112 113 119 public static Parameters buildParameters(Map expressions, List mapStack) throws PatternException { 120 if (expressions == null || expressions.size() == 0) { 121 return Parameters.EMPTY_PARAMETERS; 122 } 123 124 Parameters result = new Parameters(); 125 126 Iterator iter = expressions.entrySet().iterator(); 127 while (iter.hasNext()) { 128 Map.Entry entry = (Map.Entry )iter.next(); 129 result.setParameter( 130 ((MapStackResolver)entry.getKey()).resolve(mapStack), 131 ((MapStackResolver)entry.getValue()).resolve(mapStack) 132 ); 133 } 134 135 return result; 136 } 137 138 144 public static Map resolveMap(Map expressions, List mapStack) throws PatternException { 145 int size; 146 if (expressions == null || (size = expressions.size()) == 0) { 147 return EMPTY_MAP; 148 } 149 150 Map result = new HashMap (size); 151 152 Iterator iter = expressions.entrySet().iterator(); 153 while (iter.hasNext()) { 154 Map.Entry entry = (Map.Entry )iter.next(); 155 result.put( 156 ((MapStackResolver)entry.getKey()).resolve(mapStack), 157 ((MapStackResolver)entry.getValue()).resolve(mapStack) 158 ); 159 } 160 161 return result; 162 } 163 164 168 private static class NullResolver extends MapStackResolver { 169 private String originalExpr = null; 170 private String expression = null; 171 172 public NullResolver(String expression) { 173 if (expression != null) { 174 this.originalExpr = expression; 175 this.expression = unescape(expression); 176 } 177 } 178 179 public String toString() { 180 return this.originalExpr; 181 } 182 183 public final String resolve(List mapStack) { 184 return this.expression; 185 } 186 } 187 188 190 193 private static class CompiledResolver extends MapStackResolver { 194 private String originalExpr; 195 196 private String [] strings; 197 private int[] levels; 198 199 public CompiledResolver(String expression) throws PatternException { 200 this.originalExpr = expression; 201 compile(expression); 202 } 203 204 public String toString() { 205 return this.originalExpr; 206 } 207 208 private void compile(String expr) throws PatternException { 209 211 List stringList = new ArrayList (); 212 List levelList = new ArrayList (); 213 214 int length = expr.length(); 215 int prev = 0; 217 comp : while(prev < length) { 218 int pos = prev; 220 while(pos < length && 221 (pos = expr.indexOf('{', pos)) != -1 && 222 (pos != 0 && expr.charAt(pos - 1) == '\\')) { 223 pos++; 224 } 225 226 if (pos >= length || pos == -1) { 227 if (prev < length) { 229 stringList.add(unescape(expr.substring(prev))); 230 levelList.add(new Integer (-1)); 231 } 232 break comp; 233 } 234 235 pos++; 237 238 if (prev < pos-1) { 240 stringList.add(unescape(expr.substring(prev, pos - 1))); 241 levelList.add(new Integer (-1)); 242 } 243 244 int level = 1; while(expr.startsWith("../", pos)) { 247 level++; 248 pos += "../".length(); 249 } 250 251 int end = expr.indexOf('}', pos); 252 if (end == -1) { 253 throw new PatternException("Unmatched '{' in " + expr); 254 } 255 256 stringList.add(expr.substring(pos, end)); 257 levelList.add(new Integer (level)); 258 259 prev = end + 1; 260 } 261 262 this.strings = new String [stringList.size()]; 263 this.levels = new int[stringList.size()]; 264 for (int i = 0; i < strings.length; i++) { 265 this.strings[i] = (String )stringList.get(i); 266 this.levels[i] = ((Integer )levelList.get(i)).intValue(); 267 } 268 } 269 270 public final String resolve(List mapStack) throws PatternException { 271 StringBuffer result = new StringBuffer (); 272 int stackSize = mapStack.size(); 273 274 for (int i = 0; i < this.strings.length; i++) { 275 int level = this.levels[i]; 276 if (level == -1) { 277 result.append(this.strings[i]); 278 279 } else { 280 if (level > stackSize) { 281 throw new PatternException("Error while evaluating '" + this.originalExpr + 282 "' : not so many levels"); 283 } 284 285 Object value = ((Map )mapStack.get(stackSize - level)).get(this.strings[i]); 286 if (value != null) { 287 result.append(value); 288 } 289 } 290 } 291 292 return result.toString(); 293 } 294 295 } 304 305 } 317 | Popular Tags |