001: /**
002: * MVEL (The MVFLEX Expression Language)
003: *
004: * Copyright (C) 2007 Christopher Brock, MVFLEX/Valhalla Project and the Codehaus
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: *
018: */package org.mvel.ast;
019:
020: import org.mvel.CompileException;
021: import org.mvel.MVEL;
022: import org.mvel.compiler.ExecutableStatement;
023: import org.mvel.integration.VariableResolverFactory;
024: import org.mvel.integration.impl.DefaultLocalVariableResolverFactory;
025: import org.mvel.integration.impl.ItemResolverFactory;
026: import static org.mvel.util.ParseTools.subCompileExpression;
027: import static org.mvel.util.ParseTools.subset;
028:
029: /**
030: * @author Christopher Brock
031: */
032: public class ForEachNode extends BlockNode {
033: protected String item;
034:
035: private char[] cond;
036: protected ExecutableStatement condition;
037: protected ExecutableStatement compiledBlock;
038:
039: public ForEachNode(char[] condition, char[] block, int fields) {
040: // super(condition, fields);
041:
042: this .fields = fields;
043:
044: handleCond(this .name = condition);
045:
046: this .block = block;
047:
048: if ((fields & COMPILE_IMMEDIATE) != 0) {
049: this .compiledBlock = (ExecutableStatement) subCompileExpression(block);
050: }
051: }
052:
053: public Object getReducedValueAccelerated(Object ctx,
054: Object this Value, VariableResolverFactory factory) {
055:
056: ItemResolverFactory.ItemResolver itemR = new ItemResolverFactory.ItemResolver(
057: item);
058: ItemResolverFactory itemFactory = new ItemResolverFactory(
059: itemR, new DefaultLocalVariableResolverFactory(factory));
060:
061: Object iterCond = condition.getValue(ctx, this Value, factory);
062:
063: if (iterCond instanceof Iterable) {
064: for (Object o : (Iterable) iterCond) {
065: itemR.setValue(o);
066: compiledBlock.getValue(ctx, this Value, itemFactory);
067: }
068: } else if (iterCond instanceof Object[]) {
069: for (Object o : (Object[]) iterCond) {
070: itemR.setValue(o);
071: compiledBlock.getValue(ctx, this Value, itemFactory);
072: }
073: } else if (iterCond instanceof CharSequence) {
074: for (Object o : iterCond.toString().toCharArray()) {
075: itemR.setValue(o);
076: compiledBlock.getValue(ctx, this Value, itemFactory);
077: }
078: } else if (iterCond instanceof Integer) {
079: int max = (Integer) iterCond + 1;
080: for (int i = 1; i != max; i++) {
081: itemR.setValue(i);
082: compiledBlock.getValue(ctx, this Value, itemFactory);
083: }
084: } else {
085: throw new CompileException("non-iterable type: "
086: + iterCond.getClass().getName());
087: }
088:
089: return null;
090: }
091:
092: public Object getReducedValue(Object ctx, Object this Value,
093: VariableResolverFactory factory) {
094: ItemResolverFactory.ItemResolver itemR = new ItemResolverFactory.ItemResolver(
095: item);
096: ItemResolverFactory itemFactory = new ItemResolverFactory(
097: itemR, new DefaultLocalVariableResolverFactory(factory));
098:
099: Object iterCond = MVEL.eval(cond, this Value, factory);
100:
101: ExecutableStatement cBlockLocal = (ExecutableStatement) subCompileExpression(block);
102:
103: if (iterCond instanceof Iterable) {
104: for (Object o : (Iterable) iterCond) {
105: itemR.setValue(o);
106: cBlockLocal.getValue(ctx, this Value, itemFactory);
107: }
108: } else if (iterCond instanceof Object[]) {
109: for (Object o : (Object[]) iterCond) {
110: itemR.setValue(o);
111: cBlockLocal.getValue(ctx, this Value, itemFactory);
112: }
113: } else if (iterCond instanceof CharSequence) {
114: for (Object o : iterCond.toString().toCharArray()) {
115: itemR.setValue(o);
116: cBlockLocal.getValue(ctx, this Value, itemFactory);
117: }
118: } else if (iterCond instanceof Integer) {
119: int max = (Integer) iterCond + 1;
120: for (int i = 1; i != max; i++) {
121: itemR.setValue(i);
122: cBlockLocal.getValue(ctx, this Value, itemFactory);
123: }
124: } else {
125: throw new CompileException("non-iterable type: "
126: + iterCond.getClass().getName());
127: }
128:
129: return null;
130: }
131:
132: private void handleCond(char[] condition) {
133: int cursor = 0;
134: while (cursor < condition.length && condition[cursor] != ':')
135: cursor++;
136:
137: if (cursor == condition.length || condition[cursor] != ':')
138: throw new CompileException("expected : in foreach");
139:
140: item = new String(condition, 0, cursor).trim();
141: this .cond = subset(condition, ++cursor);
142:
143: if ((fields & COMPILE_IMMEDIATE) != 0) {
144: this .condition = (ExecutableStatement) subCompileExpression(this.cond);
145: }
146: }
147: }
|