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();
+ }
+}