You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by vg...@apache.org on 2004/09/24 15:24:59 UTC

svn commit: rev 47153 - cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/variables

Author: vgritsenko
Date: Fri Sep 24 06:24:59 2004
New Revision: 47153

Added:
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/variables/VariableExpressionTokenizer.java   (contents, props changed)
Modified:
   cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/variables/PreparedVariableResolver.java
Log:
Extract expression parser out of variable resolver (for reuse)


Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/variables/PreparedVariableResolver.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/variables/PreparedVariableResolver.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/variables/PreparedVariableResolver.java	Fri Sep 24 06:24:59 2004
@@ -71,120 +71,53 @@
     }
 
     public PreparedVariableResolver(String expr, ServiceManager manager) throws PatternException {
-
         super(expr);
         this.manager = manager;
-        this.selector = null;
-
-        int openCount = 0;
-        int closeCount = 0;
-
-        needsMapStack = false;
-
-        tokens = new ArrayList();
-        int pos = 0;
-        int i;
-        boolean escape = false;
-
-        for (i = 0; i < expr.length(); i++) {
-            char c = expr.charAt(i);
-            if (escape) {
-                escape = false;
-            } else if (c == '\\' && i < expr.length()) {
-                char nextChar = expr.charAt(i + 1);
-                if (nextChar == '{' || nextChar == '}') {
-                    expr = expr.substring(0, i) + expr.substring(i + 1);
-                    escape = true;
-                    i--;
-                }
-            } else if (c == '{') {
-                if (i > pos) {
-                    tokens.add(new Token(expr.substring(pos, i)));
-                }
+        this.tokens = new ArrayList();
 
-                openCount++;
-                tokens.add(OPEN_TOKEN);
-
-                int colonPos = indexOf(expr, ":", i);
-                int closePos = indexOf(expr, "}", i);
-                int openPos = indexOf(expr, "{", i);
-
-                if (openPos < colonPos && openPos < closePos) {
-                    throw new PatternException("Invalid '{' at position " + i + " in expression \"" + expr + "\"");
-                }
-
-                if (colonPos < closePos) {
-                    // we've found a module
-                    Token token;
-                    String module = expr.substring(i + 1, colonPos);
-
-                    if (module.equals("sitemap")) {
-                        // Explicit prefix for sitemap variable
-                        needsMapStack = true;
-                        token = new Token(SITEMAP_VAR);
-                    } else if (module.startsWith("#")) {
-                        // anchor syntax refering to a name result level
+        VariableExpressionTokenizer.tokenize(expr, new VariableExpressionTokenizer.TokenReciever() {
+            public void addToken(int type, String value) throws PatternException {
+                switch (type) {
+                    case VariableExpressionTokenizer.TokenReciever.COLON:
+                        tokens.add(COLON_TOKEN);
+                        break;
+                    case VariableExpressionTokenizer.TokenReciever.OPEN:
+                        tokens.add(OPEN_TOKEN);
+                        break;
+                    case VariableExpressionTokenizer.TokenReciever.CLOSE:
+                        tokens.add(CLOSE_TOKEN);
+                        break;
+                    case VariableExpressionTokenizer.TokenReciever.TEXT:
+                        tokens.add(new Token(value));
+                        break;
+                    case VariableExpressionTokenizer.TokenReciever.MODULE:
+                        Token token;
+                        if (value.equals("sitemap")) {
+                            // Explicit prefix for sitemap variable
+                            needsMapStack = true;
+                            token = new Token(SITEMAP_VAR);
+                        } else if (value.startsWith("#")) {
+                            // anchor syntax refering to a name result level
+                            needsMapStack = true;
+                            token = new Token(ANCHOR_VAR, value.substring(1));
+                        } else {
+                            // Module used
+                            token = getNewModuleToken(value);
+                        }
+                        tokens.add(token);
+                        break;
+                    case VariableExpressionTokenizer.TokenReciever.VARIABLE:
                         needsMapStack = true;
-                        token = new Token(ANCHOR_VAR, module.substring(1));
-                    } else {
-                        // Module used
-                        token = getNewModuleToken(module);
-                    }
-                    tokens.add(token);
-                    i = colonPos - 1;
-                } else {
-                    // Unprefixed name : sitemap variable
-                    needsMapStack = true;
-                    tokens.add(getNewSitemapToken(expr.substring(i + 1, closePos)));
-                    i = closePos - 1;
+                        tokens.add(getNewVariableToken(value));
+                        break;
+                    default:
+                        throw new IllegalArgumentException("Unknown token type: " + type);
                 }
-
-                pos = i + 1;
-            } else if (c == '}') {
-                if (i > 0 && expr.charAt(i - 1) == '\\') {
-                    continue;
-                }
-                if (i > pos) {
-                    tokens.add(new Token(expr.substring(pos, i)));
-                }
-
-                closeCount++;
-                tokens.add(CLOSE_TOKEN);
-                pos = i + 1;
-            } else if (c == ':') {
-                if (i != pos || tokens.size() == 0) {
-                    // this colon isn't part of a module reference
-                    continue;
-                }
-
-                int lastTokenType = ((Token) tokens.get(tokens.size() - 1)).getType();
-                if (lastTokenType != SITEMAP_VAR &&
-                        lastTokenType != ANCHOR_VAR &&
-                        lastTokenType != THREADSAFE_MODULE &&
-                        lastTokenType != STATEFUL_MODULE) {
-                    continue;
-                }
-
-                tokens.add(COLON_TOKEN);
-                pos = i + 1;
             }
-        }
-
-        if (i > pos) {
-            tokens.add(new Token(expr.substring(pos, i)));
-        }
-
-        if (openCount != closeCount) {
-            throw new PatternException("Mismatching braces in expression: " + expr);
-        }
-    }
-
-    private int indexOf(String expr, String chr, int pos) {
-        int location;
-        return (location = expr.indexOf(chr, pos+1))!=-1 ? location : expr.length();
+        });
     }
 
-    private Token getNewSitemapToken(String variable) {
+    private Token getNewVariableToken(String variable) {
         if (variable.startsWith("/")) {
             return new Token(ROOT_SITEMAP_VARIABLE, variable.substring(1));
         } else {

Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/variables/VariableExpressionTokenizer.java
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/treeprocessor/variables/VariableExpressionTokenizer.java	Fri Sep 24 06:24:59 2004
@@ -0,0 +1,140 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.treeprocessor.variables;
+
+import org.apache.cocoon.sitemap.PatternException;
+
+/**
+ * Parses "Text {module:{module:attribute}} more text {variable}" types of
+ * expressions. Supports escaping of braces with '\' character, and nested
+ * expressions.
+ *
+ * @version CVS $Id$
+ */
+public final class VariableExpressionTokenizer {
+
+    /**
+     * Callback for tokenizer
+     */
+    public interface TokenReciever {
+        int OPEN = -2;
+        int CLOSE = -3;
+        int COLON = -4;
+        int TEXT = -5;
+        int MODULE = -6;
+        int VARIABLE = -8;
+
+        /**
+         * Reports parsed tokens.
+         */
+        void addToken(int type, String value) throws PatternException;
+    }
+
+    /**
+     * Tokenizes specified expression. Passes tokens to the
+     * reciever.
+     *
+     * @throws PatternException if expression is not valid
+     */
+    public static void tokenize(String expression, TokenReciever reciever) throws PatternException {
+
+        int lastTokenType = 0;
+
+        int openCount = 0;
+        int closeCount = 0;
+
+        int pos = 0;
+        int i;
+        boolean escape = false;
+
+        for (i = 0; i < expression.length(); i++) {
+            final char c = expression.charAt(i);
+
+            if (escape) {
+                escape = false;
+            } else if (c == '\\' && i < expression.length()) {
+                char nextChar = expression.charAt(i + 1);
+                if (nextChar == '{' || nextChar == '}') {
+                    expression = expression.substring(0, i) + expression.substring(i + 1);
+                    escape = true;
+                    i--;
+                }
+            } else if (c == '{') {
+                if (i > pos) {
+                    reciever.addToken(lastTokenType = TokenReciever.TEXT, expression.substring(pos, i));
+                }
+
+                openCount++;
+                reciever.addToken(lastTokenType = TokenReciever.OPEN, null);
+
+                int colonPos = indexOf(expression, ':', i);
+                int closePos = indexOf(expression, '}', i);
+                int openPos = indexOf(expression, '{', i);
+
+                if (openPos < colonPos && openPos < closePos) {
+                    throw new PatternException("Invalid '{' at position " + i +
+                                               " in expression \"" + expression + "\"");
+                }
+
+                if (colonPos < closePos) {
+                    // we've found a module
+                    String module = expression.substring(i + 1, colonPos);
+                    reciever.addToken(lastTokenType = TokenReciever.MODULE, module);
+                    i = colonPos - 1;
+                } else {
+                    // Unprefixed name: variable
+                    reciever.addToken(lastTokenType = TokenReciever.VARIABLE, expression.substring(i + 1, closePos));
+                    i = closePos - 1;
+                }
+
+                pos = i + 1;
+            } else if (c == '}') {
+                if (i > 0 && expression.charAt(i - 1) == '\\') {
+                    continue;
+                }
+                if (i > pos) {
+                    reciever.addToken(lastTokenType = TokenReciever.TEXT, expression.substring(pos, i));
+                }
+
+                closeCount++;
+                reciever.addToken(lastTokenType = TokenReciever.CLOSE, null);
+
+                pos = i + 1;
+            } else if (c == ':') {
+                if (lastTokenType != TokenReciever.MODULE || i != pos) {
+                    // this colon isn't part of a module reference
+                    continue;
+                }
+
+                reciever.addToken(lastTokenType = TokenReciever.COLON, null);
+                pos = i + 1;
+            }
+        }
+
+        if (i > pos) {
+            reciever.addToken(lastTokenType = TokenReciever.TEXT, expression.substring(pos, i));
+        }
+
+        if (openCount != closeCount) {
+            throw new PatternException("Mismatching braces in expression \"" + expression + "\"");
+        }
+    }
+
+    private static int indexOf(String expression, char chr, int pos) {
+        int location;
+        return (location = expression.indexOf(chr, pos + 1)) != -1? location : expression.length();
+    }
+}