sylvain 02/01/16 01:27:59
Modified: src/scratchpad/src/org/apache/cocoon/treeprocessor
MapStackResolver.java
Log:
Precompile {..} expressions to speed up substitution.
Revision Changes Path
1.3 +110 -51
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/treeprocessor/MapStackResolver.java
Index: MapStackResolver.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/treeprocessor/MapStackResolver.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- MapStackResolver.java 15 Jan 2002 11:10:52 -0000 1.2
+++ MapStackResolver.java 16 Jan 2002 09:27:58 -0000 1.3
@@ -18,7 +18,7 @@
* Utility class for handling {...} pattern substitutions from a List of
Maps.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a>
- * @version CVS $Revision: 1.2 $ $Date: 2002/01/15 11:10:52 $
+ * @version CVS $Revision: 1.3 $ $Date: 2002/01/16 09:27:58 $
*/
public abstract class MapStackResolver {
@@ -102,7 +102,8 @@
*/
public static MapStackResolver getResolver(String expression) throws
PatternException {
if (needsResolve(expression)) {
- return new RealResolver(expression);
+// return new RealResolver(expression);
+ return new CompiledResolver(expression);
} else {
return new NullResolver(expression);
}
@@ -180,73 +181,131 @@
}
//-------------------------------------------------------------------------
+
/**
- * Real resolver for expressions containing {..} patterns
+ * Compiled form for faster substitution
*/
-
-// TODO : for now, just borrowed from AbstractSitemap, but the
-// pattern should be precompiled for faster substitution.
- private static class RealResolver extends MapStackResolver {
+ private static class CompiledResolver extends MapStackResolver {
private String originalExpr;
- private String expression;
+
+ private String[] strings;
+ private int[] levels;
- public RealResolver(String expression) throws PatternException {
+ public CompiledResolver(String expression) throws PatternException {
this.originalExpr = expression;
- this.expression = expression;
+ compile(expression);
}
public String toString() {
return this.originalExpr;
}
+
+ private void compile(String expr) throws PatternException {
+ // We're sure here that expr *contains* some substitutions
+
+ List stringList = new ArrayList();
+ List levelList = new ArrayList();
+
+ int length = expr.length();
+ int prev = 0; // position after last closing brace
- public String resolve(List mapStack) throws PatternException {
- if (expression == null) {
- return null;
+ comp : while(prev < length) {
+ // find next unescaped '{'
+ int pos = prev;
+ while(pos < length &&
+ (pos = expr.indexOf('{', pos)) != -1 &&
+ (pos != 0 && expr.charAt(pos - 1) == '\\')) {
+ pos++;
+ }
+
+ if (pos >= length || pos == -1) {
+ // no more braces
+ if (prev < length - 1) {
+ stringList.add(unescape(expr.substring(prev)));
+ levelList.add(new Integer(-1));
+ }
+ break comp;
+ }
+
+ // Pass closing brace
+ pos++;
+
+ // Add litteral strings between closing and next opening
brace
+ if (prev < pos-1) {
+ stringList.add(unescape(expr.substring(prev, pos - 1)));
+ levelList.add(new Integer(-1));
+ }
+
+ // Determine subst level
+ int level = 1; // Start at 1 since it will be substracted
from list.size()
+ while(expr.startsWith("../", pos)) {
+ level++;
+ pos += "../".length();
+ }
+
+ int end = expr.indexOf('}', pos);
+ if (end == -1) {
+ throw new PatternException("Unmatched '{' in " + expr);
+ }
+
+ stringList.add(expr.substring(pos, end));
+ levelList.add(new Integer(level));
+
+ prev = end + 1;
+ }
+
+ this.strings = new String[stringList.size()];
+ this.levels = new int[stringList.size()];
+ for (int i = 0; i < strings.length; i++) {
+ this.strings[i] = (String)stringList.get(i);
+ this.levels[i] = ((Integer)levelList.get(i)).intValue();
}
+ }
+
+ public String resolve(List mapStack) throws PatternException {
StringBuffer result = new StringBuffer();
- String s = null;
- int j = 0;
- int k = 0;
- int l = 0;
- int m = 0;
- int ii = 0;
- int i = -1;
- try {
- while (ii <= expression.length() && (i =
expression.indexOf('{', ii)) != -1) {
- result.append(expression.substring(ii, i));
- j = expression.indexOf('}', i);
- if (j < i) {
- throw new PatternException("invalid expression in
\"" + expression + "\"");
+ int stackSize = mapStack.size();
+
+ for (int i = 0; i < this.strings.length; i++) {
+ int level = this.levels[i];
+ if (level == -1) {
+ result.append(this.strings[i]);
+
+ } else {
+ if (level >= stackSize) {
+ throw new PatternException("Error while evaluating
'" + this.originalExpr +
+ "' : not so many levels");
}
- ii = j + 1;
- k = mapStack.size() - 1;
- s = expression.substring(i + 1, j);
- l = -3;
- m = -1;
- while ((l = s.indexOf("../", l + 3)) != -1) {
- k--;
- m = l;
+
+ Object value = ((Map)mapStack.get(stackSize -
level)).get(this.strings[i]);
+ if (value != null) {
+ result.append(value);
}
- if (m != -1) {
- s = s.substring(m + 3);
- }
- Object value = ((Map)mapStack.get(k)).get(s);
- if (value != null){
- result.append(value.toString());
- //getLogger().debug("Substitute evaluated value for
" + s + " as " + value);
- }else{
- //getLogger().warn("Substitute: value not found for
" + s + " while evaluating " + expression);
- }
- }
- if (ii < expression.length()) {
- result.append(expression.substring(ii));
}
- return (result.toString());
- } catch (Exception e) {
- //getLogger().error("AbstractSitemap:substitute()", e);
- throw new PatternException("error occurred during evaluation
of expression \"" + expression + "\" at position " +
- (i + 1) + " : " + e.getMessage(), e);
}
+
+ return result.toString();
}
+
+// public void dump() {
+// System.out.println(this.originalExpr + " compiled in :");
+// for (int i = 0; i < this.strings.length; i++) {
+// System.out.print("[" + this.levels[i] + ":'" +
this.strings[i] + "'] ");
+// }
+// System.out.println();
+// System.out.println();
+// }
}
+
+// public static void main(String [] args) throws Exception {
+//
+// new CompiledResolver("&{../../blah}").dump();
+// new CompiledResolver("{t1}tt{t2}").dump();
+// new CompiledResolver("\\{t1}tt{t2}xx").dump();
+// new CompiledResolver("{t1}tt\\{t2}xx").dump();
+// new CompiledResolver("{t1}tt{t2}xx").dump();
+// new CompiledResolver("xx{../t1}{../../../t2}zz").dump();
+// new CompiledResolver("xx{../t1}\\{../../../t2}zz").dump();
+//
+// }
}
----------------------------------------------------------------------
In case of troubles, e-mail: [EMAIL PROTECTED]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]