001: /*
002: * $Id: Context.java,v 1.6 2002/07/03 23:03:44 skavish Exp $
003: *
004: * ==========================================================================
005: *
006: * The JGenerator Software License, Version 1.0
007: *
008: * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
009: *
010: * Redistribution and use in source and binary forms, with or without
011: * modification, are permitted provided that the following conditions are met:
012: *
013: * 1. Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * 2. Redistributions in binary form must reproduce the above copyright
017: * notice, this list of conditions and the following disclaimer in
018: * the documentation and/or other materials provided with the
019: * distribution.
020: *
021: * 3. The end-user documentation included with the redistribution, if
022: * any, must include the following acknowlegement:
023: * "This product includes software developed by Dmitry Skavish
024: * (skavish@usa.net, http://www.flashgap.com/)."
025: * Alternately, this acknowlegement may appear in the software itself,
026: * if and wherever such third-party acknowlegements normally appear.
027: *
028: * 4. The name "The JGenerator" must not be used to endorse or promote
029: * products derived from this software without prior written permission.
030: * For written permission, please contact skavish@usa.net.
031: *
032: * 5. Products derived from this software may not be called "The JGenerator"
033: * nor may "The JGenerator" appear in their names without prior written
034: * permission of Dmitry Skavish.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
040: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: *
049: */
050:
051: package org.openlaszlo.iv.flash.context;
052:
053: import java.io.*;
054: import java.util.*;
055: import java.lang.reflect.*;
056: import org.openlaszlo.iv.flash.util.*;
057:
058: /**
059: * Abstract generator context<BR>
060: * Contains variables with theirs values and reference to parent context<BR>
061: *
062: * @author Dmitry Skavish
063: * @author James Taylor
064: */
065:
066: public abstract class Context {
067:
068: private Context parent;
069:
070: /**
071: * Sets parent context
072: *
073: * @param parent parent context
074: */
075: public void setParent(Context parent) {
076: this .parent = parent;
077: }
078:
079: /**
080: * Returns parent context
081: *
082: * @return parent context
083: */
084: public Context getParent() {
085: return parent;
086: }
087:
088: /**
089: * Retrieves value by name
090: *
091: * @param name expression to evaluate in this context
092: * @return value of variable or null
093: */
094: public abstract String getValue(String name);
095:
096: /**
097: * Queries the parent context for the value
098: *
099: * @param expr expression to evaluate in parent context
100: * @return the value of evaluating the expression in the parent context,
101: * or null if there is no parent context.
102: */
103: protected String getValueFromParent(String expr) {
104: if (parent != null) {
105: return parent.getValue(expr);
106: } else {
107: return null;
108: }
109: }
110:
111: /**
112: * Traverse the tree of context and find the root - CommandContext
113: *
114: * @return found CommandContext or null
115: */
116: public CommandContext getCommandContext() {
117: if (this instanceof CommandContext)
118: return (CommandContext) this ;
119: if (parent != null)
120: return parent.getCommandContext();
121: return null;
122: }
123:
124: /**
125: * Applies this context to the specified string<BR>
126: * In the specified string replaces all constructions like: {variable_name}
127: * with corresponding variable's value or empty string if variable not found<BR>
128: * {{ treated as a single brace
129: *
130: * @param s string to replace in
131: * @return string with all variables replaced by their values
132: */
133: public String apply(String s) {
134: if (s == null)
135: return s;
136: int start = s.indexOf('{');
137: if (start == -1)
138: return s;
139:
140: //System.out.println( "length="+s.length()+", apply='"+s+"'" );
141: int pos = 0;
142: int from = 0;
143: int slen = s.length();
144: int extra = 10;
145: char[] sa = new char[slen + extra];
146:
147: for (;;) {
148: int start1 = start + 1;
149: if (start1 < slen && s.charAt(start1) == '{') {
150: // case: {{
151: s.getChars(from, start1, sa, pos);
152: pos += start1 - from;
153: from = start1 + 1;
154: } else {
155: int cnt = 1;
156: int end = start1;
157: while (end < slen && cnt > 0) {
158: char ch = s.charAt(end++);
159: if (ch == '}')
160: cnt--;
161: else if (ch == '{')
162: cnt++;
163: }
164: end--;
165: if (end >= slen) {
166: s.getChars(from, start, sa, pos);
167: pos += start - from;
168: break;
169: }
170: s.getChars(from, end, sa, pos);
171: pos += start - from;
172:
173: // get variable name
174: String varName = new String(sa, pos + 1, end - start1);
175: String value = null;
176:
177: int varlen = varName.length();
178: if (varlen > 0) {
179: char ch = varName.charAt(0);
180: if (ch == '$') { // check for command
181: String cmdCall = apply(varName).trim();
182: CommandContext cmdexec = getCommandContext();
183: if (cmdexec == null) {
184: value = getValue(cmdCall);
185: } else {
186: value = cmdexec.executeCommand(this ,
187: cmdCall);
188: }
189: } else if (ch == '#' && varlen > 1) { // check for inline javascript, convinient way to use js
190: String js_text = varName.substring(1);
191: value = Util.executeJSString(this , js_text,
192: null);
193: } else {
194: String varName1 = apply(varName).trim();
195: value = getValue(varName1);
196: }
197: }
198:
199: if (value != null) {
200: int vlen = value.length();
201: int vnlen = varName.length() + 2; // including braces
202:
203: // bug fixed - by yoonforh 2002-05-28 13:39:34
204: if (vlen > vnlen) {
205: extra -= (vlen - vnlen);
206: if (extra < 0) {
207: extra = -extra;
208: char[] t = new char[sa.length + extra * 2];
209: System.arraycopy(sa, 0, t, 0, sa.length);
210: sa = t;
211: }
212: }
213: value.getChars(0, vlen, sa, pos);
214: pos += vlen;
215: }
216: from = end + 1;
217: }
218: start = s.indexOf('{', from);
219: if (start == -1) {
220: s.getChars(from, slen, sa, pos);
221: pos += slen - from;
222: break;
223: }
224: }
225:
226: return new String(sa, 0, pos);
227: }
228: }
|