001: package org.gui4j.core.call;
002:
003: import java.io.Serializable;
004: import java.util.ArrayList;
005: import java.util.List;
006: import java.util.Map;
007:
008: import org.gui4j.core.Gui4jCall;
009: import org.gui4j.core.Gui4jCallFactory;
010: import org.gui4j.core.Gui4jComponent;
011: import org.gui4j.core.Gui4jMap1;
012: import org.gui4j.core.Gui4jTypeCheck;
013: import org.gui4j.event.Gui4jEvent;
014: import org.gui4j.exception.ErrorTags;
015: import org.gui4j.exception.Gui4jUncheckedException;
016:
017: final public class Gui4jCallParser implements Gui4jCallFactory,
018: ErrorTags, Serializable {
019:
020: /**
021: * Constructor for Gui4jCallParser.
022: */
023: public Gui4jCallParser() {
024: super ();
025: }
026:
027: /* (non-Javadoc)
028: * @see org.gui4j.core.Gui4jCallFactory#getInstance(org.gui4j.core.Gui4jComponent, int, java.lang.String)
029: */
030: public Gui4jCall getInstance(Gui4jComponent gui4jComponent,
031: int lineNumber, String accessPath) {
032: Map m = null;
033: return getInstance(gui4jComponent, lineNumber, m, accessPath);
034: }
035:
036: /* (non-Javadoc)
037: * @see org.gui4j.core.Gui4jCallFactory#getInstance(org.gui4j.core.Gui4jComponent, int, java.lang.Class, java.lang.String)
038: */
039: public Gui4jCall getInstance(Gui4jComponent gui4jComponent,
040: int lineNumber, Class valueClass, String accessPath) {
041: Map m = new Gui4jMap1("", valueClass);
042: return getInstance(gui4jComponent, lineNumber, m, accessPath);
043: }
044:
045: /* (non-Javadoc)
046: * @see org.gui4j.core.Gui4jCallFactory#getInstance(org.gui4j.core.Gui4jComponent, int, java.util.Map, java.lang.String)
047: */
048: public Gui4jCall getInstance(Gui4jComponent gui4jComponent,
049: int lineNumber, Map valueClassMap, String accessPath) {
050: Class baseClass = gui4jComponent.getGui4jComponentContainer()
051: .getGui4jControllerClass();
052: if (accessPath == null) {
053: return null;
054: }
055:
056: Gui4jAccessImpl baseAccess = new Gui4jAccessBase(baseClass);
057:
058: ParseCtx parseCtx = new ParseCtx(this , gui4jComponent,
059: lineNumber, valueClassMap, baseAccess, accessPath);
060:
061: List dependantProps = null;
062: if (accessPath.length() > 0 && accessPath.charAt(0) == '{') {
063: dependantProps = parseDependantProperties(parseCtx,
064: accessPath);
065: }
066:
067: if (parseCtx.i == accessPath.length()) {
068: return new Gui4jDefaultCall(gui4jComponent, null,
069: dependantProps, valueClassMap);
070: }
071:
072: // support for "internal action" calls,
073: // e.g. maximization of portlets
074: if (accessPath.charAt(parseCtx.i) == '!') {
075: return new Gui4jInternalActionCall(gui4jComponent,
076: accessPath.substring(parseCtx.i + 1));
077: }
078:
079: Gui4jAccessImpl result = parseSeqSequence(parseCtx, accessPath);
080: if (parseCtx.i < accessPath.length()) {
081: Object[] args = { accessPath, new Integer(parseCtx.i) };
082: throw new Gui4jUncheckedException.ResourceError(parseCtx
083: .getConfigurationName(), parseCtx.getLineNumber(),
084: RESOURCE_ERROR_access_unexpected_character, args);
085: }
086:
087: return new Gui4jDefaultCall(gui4jComponent, result,
088: dependantProps, valueClassMap, parseCtx.getUsedParams());
089: }
090:
091: private Gui4jAccessImpl getInstance(ParseCtx parseCtx,
092: Gui4jAccessImpl this Access, String accessPath) {
093: int pos = parseCtx.i;
094: int len = accessPath.length();
095: if (pos >= len) {
096: Object[] args = { accessPath, new Integer(pos) };
097: throw new Gui4jUncheckedException.ResourceError(parseCtx
098: .getConfigurationName(), parseCtx.getLineNumber(),
099: RESOURCE_ERROR_access_unexpected_end, args);
100: }
101:
102: switch (accessPath.charAt(pos)) {
103: case '\'':
104: return new Gui4jAccessConstant(parseCtx, accessPath);
105: case '{':
106: case '}':
107: case ')':
108: case ',':
109: case '.':
110: case ';': {
111: Object[] args = { accessPath, new Integer(pos) };
112: throw new Gui4jUncheckedException.ResourceError(parseCtx
113: .getConfigurationName(), parseCtx.getLineNumber(),
114: RESOURCE_ERROR_access_unexpected_end, args);
115: }
116: case '(':
117: parseCtx.i = parseCtx.i + 1;
118: Gui4jAccessImpl gui4jAccess = getInstance(parseCtx,
119: this Access, accessPath);
120: if (len >= parseCtx.i
121: || accessPath.charAt(parseCtx.i) != ')') {
122: Object[] args = { accessPath, new Integer(pos) };
123: throw new Gui4jUncheckedException.ResourceError(
124: parseCtx.getConfigurationName(), parseCtx
125: .getLineNumber(),
126: RESOURCE_ERROR_access_unexpected_character,
127: args);
128: } else {
129: parseCtx.i = parseCtx.i + 1; // skip ')'
130: }
131: return gui4jAccess;
132: case ':':
133: return new Gui4jAccessStatic(parseCtx, accessPath);
134: case '~':
135: return new Gui4jAccessBoolean(parseCtx, accessPath);
136: case '0':
137: case '1':
138: case '2':
139: case '3':
140: case '4':
141: case '5':
142: case '6':
143: case '7':
144: case '8':
145: case '9': {
146: boolean isDouble = false;
147: int i = pos;
148: while (i < len) {
149: char c = accessPath.charAt(i);
150: if (c == '.') {
151: isDouble = true;
152: break;
153: } else if (c >= '0' && c <= '9') {
154: // go to next character
155: i++;
156: } else {
157: break;
158: }
159: }
160: return isDouble ? (Gui4jAccessImpl) new Gui4jAccessDouble(
161: parseCtx, accessPath)
162: : (Gui4jAccessImpl) new Gui4jAccessInteger(
163: parseCtx, accessPath);
164: }
165: case '%':
166: return new Gui4jAccessCharacter(parseCtx, accessPath);
167: case '$':
168: parseCtx.i = parseCtx.i + 1;
169: return parseCtx.getBaseAccess();
170: case '?':
171: return new Gui4jAccessSetValue(parseCtx, accessPath);
172: default:
173: return new Gui4jAccessMethod(parseCtx, this Access,
174: accessPath);
175: }
176: }
177:
178: Gui4jAccessImpl parseCallSequence(ParseCtx parseCtx,
179: String accessPath) {
180: Gui4jAccessImpl gui4jAccess = parseCtx.getBaseAccess();
181: int len = accessPath.length();
182: do {
183: gui4jAccess = getInstance(parseCtx, gui4jAccess, accessPath);
184: if (parseCtx.i < len
185: && accessPath.charAt(parseCtx.i) == '.') {
186: parseCtx.i = parseCtx.i + 1;
187: } else {
188: return gui4jAccess;
189: }
190: } while (true);
191: }
192:
193: static void skipSpaces(ParseCtx parseCtx, int len) {
194: while (parseCtx.i < len
195: && parseCtx.mAccessPath.charAt(parseCtx.i) == ' ') {
196: parseCtx.i++;
197: }
198: }
199:
200: private Gui4jAccessImpl createSeq(Gui4jAccessImpl first,
201: Gui4jAccessImpl second) {
202: if (first == null) {
203: return second;
204: }
205: return new Gui4jAccessSeq(first, second);
206: }
207:
208: private Gui4jAccessImpl parseSeqSequence(ParseCtx parseCtx,
209: String accessPath) {
210: Gui4jAccessImpl gui4jAccess = null;
211: int len = accessPath.length();
212: do {
213: gui4jAccess = createSeq(gui4jAccess, parseCallSequence(
214: parseCtx, accessPath));
215: skipSpaces(parseCtx, len);
216: if (parseCtx.i < len
217: && accessPath.charAt(parseCtx.i) == ';') {
218: parseCtx.i = parseCtx.i + 1;
219: } else {
220: return gui4jAccess;
221: }
222: } while (true);
223: }
224:
225: private List parseDependantProperties(ParseCtx parseCtx,
226: String accessPath) {
227: List dependantProps = new ArrayList();
228: int len = accessPath.length();
229: parseCtx.i++; // skip '{'
230: loop: do {
231: Gui4jAccessImpl property = parseCallSequence(parseCtx,
232: accessPath);
233: Gui4jTypeCheck.ensureType(property.getResultClass(),
234: Gui4jEvent.class, parseCtx.getConfigurationName(),
235: accessPath);
236: dependantProps.add(new Gui4jDefaultCall(parseCtx
237: .getGui4jComponent(), property, null, null));
238: skipSpaces(parseCtx, len);
239: if (parseCtx.i < len) {
240: switch (accessPath.charAt(parseCtx.i)) {
241: case '}':
242: parseCtx.i++;
243: return dependantProps;
244: case ',':
245: parseCtx.i++;
246: break;
247: default:
248: Object[] args = { accessPath,
249: new Integer(parseCtx.i) };
250: throw new Gui4jUncheckedException.ResourceError(
251: parseCtx.getConfigurationName(), parseCtx
252: .getLineNumber(),
253: RESOURCE_ERROR_access_unexpected_character,
254: args);
255: }
256: } else {
257: Object[] args = { accessPath, new Integer(parseCtx.i) };
258: throw new Gui4jUncheckedException.ResourceError(
259: parseCtx.getConfigurationName(), parseCtx
260: .getLineNumber(),
261: RESOURCE_ERROR_access_unexpected_end, args);
262: }
263: } while (true);
264: }
265:
266: }
|