Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/tripi/asp/ForEachNode.java


1   /**
2    * ArrowHead ASP Server 
3    * This is a source file for the ArrowHead ASP Server - an 100% Java
4    * VBScript interpreter and ASP server.
5    *
6    * For more information, see http://www.tripi.com/arrowhead
7    *
8    * Copyright (C) 2002  Terence Haddock
9    *
10   * This program is free software; you can redistribute it and/or modify
11   * it under the terms of the GNU General Public License as published by
12   * the Free Software Foundation; either version 2 of the License, or
13   * (at your option) any later version.
14   *
15   * This program is distributed in the hope that it will be useful,
16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   * GNU General Public License for more details.
19   *
20   * You should have received a copy of the GNU General Public License
21   * along with this program; if not, write to the Free Software
22   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23   *
24   */
25  package com.tripi.asp;
26  
27  import java.util.Enumeration;
28  import java.lang.reflect.Array;
29  
30  import org.apache.log4j.Category;
31  
32  /**
33   * The ForEachNode class handles the FOR EACH .. IN .. statement in
34   * VBScript.
35   *
36   * @author Terence Haddock
37   * @version 0.9
38   */
39  public class ForEachNode implements Node
40  {
41      /** The debugging class */
42      Category DBG = Category.getInstance(ForEachNode.class);
43  
44      /** The identifier of the loop variable */
45      IdentNode ident;
46  
47      /** The expression we are looping through */
48      Node expr;
49  
50      /** The block to execute for each statement */
51      BlockNode block;
52  
53      /**
54       * Constructor.
55       *
56       * @param ident The identifier to use as the loop variable.
57       * @param expr The expression to loop through.
58       * @param block The block of code to execute.
59       */
60      public ForEachNode(IdentNode ident, Node expr, BlockNode block)
61      {
62          this.ident = ident;
63          this.expr = expr;
64          this.block = block;
65      }
66  
67      /**
68       * Get the ident we should use for the loop.
69       * @return ident for the loop.
70       */
71      public IdentNode getIdent()
72      {
73          return ident;
74      }
75  
76      /**
77       * Get the expression we should use for the loop.
78       * @return expression for the loop
79       */
80      public Node getExpression()
81      {
82          return expr;
83      }
84  
85      /**
86       * Get the block to use in the loop.
87       * @return block in the loop
88       */
89      public Node getBlock()
90      {
91          return block;
92      }
93  
94      /**
95       * Dumps the visual representation of this script.
96       *
97       * @throws AspException is an error occurs.
98       * @see Node#dump()
99       */
100     public void dump() throws AspException
101     {
102         System.out.print("FOR EACH ");
103         ident.dump();
104         System.out.print(" IN ");
105         expr.dump();
106         System.out.println();
107         block.dump();
108         System.out.println("NEXT");
109     }
110 
111     /**
112      * Prepares this statement for execution. Calls prepare on the block
113      * of statements contained within the for loop.
114      * @param context The context under which we are operating.
115      * @throws AspException if an error occurs.
116      * @see Node#prepare(AspContext)
117      */
118     public void prepare(AspContext context) throws AspException
119     {
120         block.prepare(context);
121     }
122 
123     /**
124      * Executes this node.
125      * @param context The context under which we are operating.
126      * @return Return value of the expression
127      * @throws AspException if an error occurs.
128      * @see Node#execute(AspContext)
129      */
130     public Object execute(AspContext context) throws AspException
131     {
132         /* Obtain the value of the expression we are using for the loop */
133         Object obj = expr.execute(context);
134         if (DBG.isDebugEnabled()) {
135             DBG.debug("ForEach called on object: " + obj);
136         }
137         /* Dereference */
138         while (obj instanceof SimpleReference &&
139             !(obj instanceof ArrayNode) &&
140             !(obj instanceof JavaObjectNode) &&
141             !(obj instanceof SimpleMap))
142         {
143             if (DBG.isDebugEnabled()) DBG.debug("Dereferencing: " +
144                 obj);
145             obj = ((SimpleReference)obj).getValue();
146         }
147         if (DBG.isDebugEnabled()) DBG.debug("Final object: " + obj);
148         /* Test if this is an instance of ArrayNode */
149         if (obj instanceof ArrayNode)
150         {
151             executeArrayNode((ArrayNode)obj, context);
152             return null;
153         }
154         /* Should be an instance of SimpleMap */
155         if (obj instanceof SimpleMap)
156         {
157             executeSimpleMap((SimpleMap)obj, context);
158             return null;
159         }
160         /* Test if this is an instance of JavaObjectNode
161            this test is last because the previous tests may override this one */
162         if (obj instanceof JavaObjectNode)
163         {
164             executeJavaObjectNode((JavaObjectNode)obj, context);
165             return null;
166         }
167         throw new AspException("FOR EACH called on non-array object: " + obj);
168     }
169 
170     /**
171      * Internal function which handles the enumeration of JavaObjectNode
172      * objects. XXX This is probably a bad idea, and should be moved somewhere
173      * else (like a new class: JavaArrayNode).
174      * @param context AspContext
175      * @throws AspException on error
176      */
177     private void executeJavaObjectNode(JavaObjectNode javaObj, AspContext context)
178         throws AspException
179     {
180         /* Find the sub-object contained in this Java object */
181         Object array = javaObj.getSubObject();
182         /* This object should be a Java array */
183         if (!array.getClass().isArray()) 
184             throw new AspException("FOR EACH called on non-array object: " + javaObj);
185         /* Loop through all of the values */
186         for (int i = 0; i < Array.getLength(array); i++)
187         {
188             Object value = Types.coerceToNode(Array.get(array, i));
189 
190             /* Set the ident to the current value */
191             context.setValue(ident, value);
192 
193             /* Execute the block, handling Exit For exceptions */
194             try {
195                 block.execute(context);
196             } catch (AspExitForException ex) {
197                 return;
198             }
199         }
200     }
201 
202     /**
203      * Internal function which handles the enumeration of ArrayNode
204      * object.
205      * @param context AspContext
206      * @throws AspException on error
207      */
208     private void executeArrayNode(ArrayNode array, AspContext context)
209         throws AspException
210     {
211         /* Obtain the upper bound of the array */
212         int upperBound = array.getUBOUND(1);
213         /* Loop through each value */
214         for (int i = 0; i <= upperBound; i++)
215         {
216             /* Create a parameter list of a single element to pass to array */
217             VarListNode vn = new VarListNode();
218             vn.append(new Integer(i));
219             /* Obtain the value at the specified index */
220             Object value = array.getIndex(vn, context);
221 
222             /* Sets the ident to the current value */
223             context.setValue(ident, value);
224 
225             try {
226                 block.execute(context);
227             } catch (AspExitForException ex) {
228                 return;
229             }
230         }
231     }
232     
233     /**
234      * Internal function which handles the enumeration of SimpleMap
235      * object.
236      * @param context AspContext
237      * @throws AspException on error
238      */
239     private void executeSimpleMap(SimpleMap map, AspContext context)
240         throws AspException
241     {
242         /* Obtain the keys of the expression */
243         Enumeration keys = map.getKeys();
244         /* Loop through the elements, executing the expression for each value */
245         while (keys.hasMoreElements())
246         {
247             Object key = keys.nextElement();
248             /* Sets the ident to the current value */
249             context.setValue(ident, key);
250 
251             try {
252                 block.execute(context);
253             } catch (AspExitForException ex) {
254                 return;
255             }
256         }
257     }
258 };
259