001: /* ExpressionFragment.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Mon Sep 3 10:50:56 2007, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2007 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zkmax.xel.util;
020:
021: import java.util.List;
022: import java.util.LinkedList;
023:
024: import org.zkoss.lang.Objects;
025:
026: /** Represents an expression fragment of an expression.
027: * When {@link #parse} is called, a list of fragments is returned.
028: * Each of them is either a Sring instnce or a {@link ExpressionFragment}
029: * instance.
030: *
031: * <p>For example, "ab${x + y}cd${z}" is broken into the following
032: * segments, when {@link #parse} is called:<br/>
033: * String("ab"), ExpressionFragment("x+y"), String("cd") and
034: * ExpressionFragment("z").
035: *
036: * <p>It is used to implement {@link org.zkoss.xel.ExpressionFactory}
037: * based on an evaluator that doesn't support the syntax of ${expr}.
038: * The users of XEL expressions rarely needs to use this class.
039: *
040: * @author tomyeh
041: * @since 3.0.0
042: */
043: public class ExpressionFragment implements java.io.Serializable {
044: private final String _expr;
045:
046: /** Parses an expression into a list of fragments.
047: * Each of them is either a Sring instnce or a {@link ExpressionFragment}
048: * instance.
049: *
050: * <p>For example, "ab${x + y}cd${z}" is broken into the following
051: * segments, when {@link #parse} is called:<br/>
052: * String("ab"), ExpressionFragment("x+y"), String("cd") and
053: * ExpressionFragment("z").
054: *
055: * @param expr the expression that may or may not contain one or
056: * multiple ${expr}. It cannot be null.
057: */
058: public static final List parse(String expr) {
059: final List frags = new LinkedList();
060: for (int j = 0, len = expr.length();;) {
061: int k = expr.indexOf("${", j);
062: int l = k >= 0 ? expr.indexOf('}', k + 2) : 0;
063: if (k < 0 || l < 0) {
064: if (j < len)
065: frags.add(unescape(expr.substring(j)));
066: return frags; //done
067: }
068:
069: if (k > j)
070: frags.add(unescape(expr.substring(j, k)));
071: if (l > k + 2)
072: frags.add(new ExpressionFragment(expr.substring(k + 2,
073: l)));
074: j = l + 1;
075: }
076: }
077:
078: /** Converts \$\{ to ${.
079: */
080: private static final String unescape(String s) {
081: StringBuffer sb = null;
082: for (int j = 0, len = s.length();;) {
083: int k = s.indexOf("\\$\\{", j);
084: if (k < 0) {
085: if (j == 0)
086: return s; //nothing to convert
087: return sb.append(s.substring(j)).toString();
088: }
089:
090: if (sb == null)
091: sb = new StringBuffer(len);
092: sb.append(s.substring(j, k)).append("${");
093: j = k + 4;
094: }
095: }
096:
097: private ExpressionFragment(String expr) {
098: _expr = expr;
099: }
100:
101: /** Returns the expression.
102: */
103: public String getExpression() {
104: return _expr;
105: }
106:
107: //Object//
108: public int hashCode() {
109: return Objects.hashCode(_expr);
110: }
111:
112: public boolean equals(Object o) {
113: return o instanceof ExpressionFragment
114: && Objects
115: .equals(_expr, ((ExpressionFragment) o)._expr);
116: }
117:
118: public String toString() {
119: return _expr;
120: }
121: }
|