KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xpath > compiler > OpMap


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: OpMap.java,v 1.16 2004/02/17 04:32:49 minchau Exp $
18  */

19 package org.apache.xpath.compiler;
20
21 import org.apache.xalan.res.XSLMessages;
22 import org.apache.xml.utils.ObjectVector;
23 import org.apache.xpath.patterns.NodeTest;
24 import org.apache.xpath.res.XPATHErrorResources;
25
26 /**
27  * This class represents the data structure basics of the XPath
28  * object.
29  */

30 public class OpMap
31 {
32
33   /**
34    * The current pattern string, for diagnostics purposes
35    */

36   protected String JavaDoc m_currentPattern;
37
38   /**
39    * Return the expression as a string for diagnostics.
40    *
41    * @return The expression string.
42    */

43   public String JavaDoc toString()
44   {
45     return m_currentPattern;
46   }
47
48   /**
49    * Return the expression as a string for diagnostics.
50    *
51    * @return The expression string.
52    */

53   public String JavaDoc getPatternString()
54   {
55     return m_currentPattern;
56   }
57
58   /**
59    * The starting size of the token queue.
60    */

61   static final int MAXTOKENQUEUESIZE = 500;
62
63   /*
64    * Amount to grow token queue when it becomes full
65    */

66   static final int BLOCKTOKENQUEUESIZE = 500;
67   
68   /**
69    * TokenStack is the queue of used tokens. The current token is the token at the
70    * end of the m_tokenQueue. The idea is that the queue can be marked and a sequence
71    * of tokens can be reused.
72    */

73   ObjectVector m_tokenQueue = new ObjectVector(MAXTOKENQUEUESIZE, BLOCKTOKENQUEUESIZE);
74
75   /**
76    * Get the XPath as a list of tokens.
77    *
78    * @return ObjectVector of tokens.
79    */

80   public ObjectVector getTokenQueue()
81   {
82     return m_tokenQueue;
83   }
84
85   /**
86    * Get the XPath as a list of tokens.
87    *
88    * @param pos index into token queue.
89    *
90    * @return The token, normally a string.
91    */

92   public Object JavaDoc getToken(int pos)
93   {
94     return m_tokenQueue.elementAt(pos);
95   }
96
97   /**
98    * The current size of the token queue.
99    */

100 // public int m_tokenQueueSize = 0;
101

102   /**
103     * Get size of the token queue.
104    *
105    * @return The size of the token queue.
106    */

107   public int getTokenQueueSize()
108   {
109     return m_tokenQueue.size();
110     
111   }
112
113   /**
114    * An operations map is used instead of a proper parse tree. It contains
115    * operations codes and indexes into the m_tokenQueue.
116    * I use an array instead of a full parse tree in order to cut down
117    * on the number of objects created.
118    */

119   OpMapVector m_opMap = null;
120
121   /**
122     * Get the opcode list that describes the XPath operations. It contains
123    * operations codes and indexes into the m_tokenQueue.
124    * I use an array instead of a full parse tree in order to cut down
125    * on the number of objects created.
126    *
127    * @return An IntVector that is the opcode list that describes the XPath operations.
128    */

129   public OpMapVector getOpMap()
130   {
131     return m_opMap;
132   }
133
134   // Position indexes
135

136   /**
137    * The length is always the opcode position + 1.
138    * Length is always expressed as the opcode+length bytes,
139    * so it is always 2 or greater.
140    */

141   public static final int MAPINDEX_LENGTH = 1;
142
143   /**
144    * Replace the large arrays
145    * with a small array.
146    */

147   void shrink()
148   {
149
150     int n = m_opMap.elementAt(MAPINDEX_LENGTH);
151     m_opMap.setToSize(n + 4);
152
153     m_opMap.setElementAt(0,n);
154     m_opMap.setElementAt(0,n+1);
155     m_opMap.setElementAt(0,n+2);
156
157
158     n = m_tokenQueue.size();
159     m_tokenQueue.setToSize(n + 4);
160
161     m_tokenQueue.setElementAt(null,n);
162     m_tokenQueue.setElementAt(null,n + 1);
163     m_tokenQueue.setElementAt(null,n + 2);
164   }
165
166   /**
167   * Given an operation position, return the current op.
168    *
169    * @param opPos index into op map.
170    * @return the op that corresponds to the opPos argument.
171    */

172   public int getOp(int opPos)
173   {
174     return m_opMap.elementAt(opPos);
175   }
176
177   /**
178   * Set the op at index to the given int.
179    *
180    * @param opPos index into op map.
181    * @param value Value to set
182    */

183   public void setOp(int opPos, int value)
184   {
185      m_opMap.setElementAt(value,opPos);
186   }
187   
188   /**
189    * Given an operation position, return the end position, i.e. the
190    * beginning of the next operation.
191    *
192    * @param opPos An op position of an operation for which there is a size
193    * entry following.
194    * @return position of next operation in m_opMap.
195    */

196   public int getNextOpPos(int opPos)
197   {
198     return opPos + m_opMap.elementAt(opPos + 1);
199   }
200
201   /**
202    * Given a location step position, return the end position, i.e. the
203    * beginning of the next step.
204    *
205    * @param opPos the position of a location step.
206    * @return the position of the next location step.
207    */

208   public int getNextStepPos(int opPos)
209   {
210
211     int stepType = getOp(opPos);
212
213     if ((stepType >= OpCodes.AXES_START_TYPES)
214             && (stepType <= OpCodes.AXES_END_TYPES))
215     {
216       return getNextOpPos(opPos);
217     }
218     else if ((stepType >= OpCodes.FIRST_NODESET_OP)
219              && (stepType <= OpCodes.LAST_NODESET_OP))
220     {
221       int newOpPos = getNextOpPos(opPos);
222
223       while (OpCodes.OP_PREDICATE == getOp(newOpPos))
224       {
225         newOpPos = getNextOpPos(newOpPos);
226       }
227
228       stepType = getOp(newOpPos);
229
230       if (!((stepType >= OpCodes.AXES_START_TYPES)
231             && (stepType <= OpCodes.AXES_END_TYPES)))
232       {
233         return OpCodes.ENDOP;
234       }
235
236       return newOpPos;
237     }
238     else
239     {
240       throw new RuntimeException JavaDoc(
241         XSLMessages.createXPATHMessage(XPATHErrorResources.ER_UNKNOWN_STEP, new Object JavaDoc[]{new Integer JavaDoc(stepType).toString()}));
242       //"Programmer's assertion in getNextStepPos: unknown stepType: " + stepType);
243
}
244   }
245
246   /**
247    * Given an operation position, return the end position, i.e. the
248    * beginning of the next operation.
249    *
250    * @param opMap The operations map.
251    * @param opPos index to operation, for which there is a size entry following.
252    * @return position of next operation in m_opMap.
253    */

254   public static int getNextOpPos(int[] opMap, int opPos)
255   {
256     return opPos + opMap[opPos + 1];
257   }
258
259   /**
260    * Given an FROM_stepType position, return the position of the
261    * first predicate, if there is one, or else this will point
262    * to the end of the FROM_stepType.
263    * Example:
264    * int posOfPredicate = xpath.getNextOpPos(stepPos);
265    * boolean hasPredicates =
266    * OpCodes.OP_PREDICATE == xpath.getOp(posOfPredicate);
267    *
268    * @param opPos position of FROM_stepType op.
269    * @return position of predicate in FROM_stepType structure.
270    */

271   public int getFirstPredicateOpPos(int opPos)
272      throws javax.xml.transform.TransformerException JavaDoc
273   {
274
275     int stepType = m_opMap.elementAt(opPos);
276
277     if ((stepType >= OpCodes.AXES_START_TYPES)
278             && (stepType <= OpCodes.AXES_END_TYPES))
279     {
280       return opPos + m_opMap.elementAt(opPos + 2);
281     }
282     else if ((stepType >= OpCodes.FIRST_NODESET_OP)
283              && (stepType <= OpCodes.LAST_NODESET_OP))
284     {
285       return opPos + m_opMap.elementAt(opPos + 1);
286     }
287     else if(-2 == stepType)
288     {
289       return -2;
290     }
291     else
292     {
293       error(org.apache.xpath.res.XPATHErrorResources.ER_UNKNOWN_OPCODE,
294             new Object JavaDoc[]{ String.valueOf(stepType) }); //"ERROR! Unknown op code: "+m_opMap[opPos]);
295
return -1;
296     }
297   }
298   
299   /**
300    * Tell the user of an error, and probably throw an
301    * exception.
302    *
303    * @param msg An error msgkey that corresponds to one of the constants found
304    * in {@link org.apache.xpath.res.XPATHErrorResources}, which is
305    * a key for a format string.
306    * @param args An array of arguments represented in the format string, which
307    * may be null.
308    *
309    * @throws TransformerException if the current ErrorListoner determines to
310    * throw an exception.
311    */

312   public void error(String JavaDoc msg, Object JavaDoc[] args) throws javax.xml.transform.TransformerException JavaDoc
313   {
314
315     java.lang.String JavaDoc fmsg = org.apache.xalan.res.XSLMessages.createXPATHMessage(msg, args);
316     
317
318     throw new javax.xml.transform.TransformerException JavaDoc(fmsg);
319   }
320
321
322   /**
323    * Go to the first child of a given operation.
324    *
325    * @param opPos position of operation.
326    *
327    * @return The position of the first child of the operation.
328    */

329   public static int getFirstChildPos(int opPos)
330   {
331     return opPos + 2;
332   }
333
334   /**
335    * Get the length of an operation.
336    *
337    * @param opPos The position of the operation in the op map.
338    *
339    * @return The size of the operation.
340    */

341   public int getArgLength(int opPos)
342   {
343     return m_opMap.elementAt(opPos + MAPINDEX_LENGTH);
344   }
345
346   /**
347    * Given a location step, get the length of that step.
348    *
349    * @param opPos Position of location step in op map.
350    *
351    * @return The length of the step.
352    */

353   public int getArgLengthOfStep(int opPos)
354   {
355     return m_opMap.elementAt(opPos + MAPINDEX_LENGTH + 1) - 3;
356   }
357
358   /**
359    * Get the first child position of a given location step.
360    *
361    * @param opPos Position of location step in the location map.
362    *
363    * @return The first child position of the step.
364    */

365   public static int getFirstChildPosOfStep(int opPos)
366   {
367     return opPos + 3;
368   }
369
370   /**
371    * Get the test type of the step, i.e. NODETYPE_XXX value.
372    *
373    * @param opPosOfStep The position of the FROM_XXX step.
374    *
375    * @return NODETYPE_XXX value.
376    */

377   public int getStepTestType(int opPosOfStep)
378   {
379     return m_opMap.elementAt(opPosOfStep + 3); // skip past op, len, len without predicates
380
}
381
382   /**
383    * Get the namespace of the step.
384    *
385    * @param opPosOfStep The position of the FROM_XXX step.
386    *
387    * @return The step's namespace, NodeTest.WILD, or null for null namespace.
388    */

389   public String JavaDoc getStepNS(int opPosOfStep)
390   {
391
392     int argLenOfStep = getArgLengthOfStep(opPosOfStep);
393
394     // System.out.println("getStepNS.argLenOfStep: "+argLenOfStep);
395
if (argLenOfStep == 3)
396     {
397       int index = m_opMap.elementAt(opPosOfStep + 4);
398
399       if (index >= 0)
400         return (String JavaDoc) m_tokenQueue.elementAt(index);
401       else if (OpCodes.ELEMWILDCARD == index)
402         return NodeTest.WILD;
403       else
404         return null;
405     }
406     else
407       return null;
408   }
409
410   /**
411    * Get the local name of the step.
412    * @param opPosOfStep The position of the FROM_XXX step.
413    *
414    * @return OpCodes.EMPTY, OpCodes.ELEMWILDCARD, or the local name.
415    */

416   public String JavaDoc getStepLocalName(int opPosOfStep)
417   {
418
419     int argLenOfStep = getArgLengthOfStep(opPosOfStep);
420
421     // System.out.println("getStepLocalName.argLenOfStep: "+argLenOfStep);
422
int index;
423
424     switch (argLenOfStep)
425     {
426     case 0 :
427       index = OpCodes.EMPTY;
428       break;
429     case 1 :
430       index = OpCodes.ELEMWILDCARD;
431       break;
432     case 2 :
433       index = m_opMap.elementAt(opPosOfStep + 4);
434       break;
435     case 3 :
436       index = m_opMap.elementAt(opPosOfStep + 5);
437       break;
438     default :
439       index = OpCodes.EMPTY;
440       break; // Should assert error
441
}
442
443     // int index = (argLenOfStep == 3) ? m_opMap[opPosOfStep+5]
444
// : ((argLenOfStep == 1) ? -3 : -2);
445
if (index >= 0)
446       return (String JavaDoc) m_tokenQueue.elementAt(index).toString();
447     else if (OpCodes.ELEMWILDCARD == index)
448       return NodeTest.WILD;
449     else
450       return null;
451   }
452   
453 }
454
Popular Tags