KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > compile > NewInvocationNode


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.NewInvocationNode
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.compile;
23
24 import org.apache.derby.iapi.services.loader.ClassInspector;
25
26 import org.apache.derby.iapi.services.context.ContextManager;
27
28 import org.apache.derby.iapi.services.compiler.MethodBuilder;
29 import org.apache.derby.iapi.services.compiler.LocalField;
30
31
32 import org.apache.derby.iapi.services.sanity.SanityManager;
33
34 import org.apache.derby.iapi.error.StandardException;
35 import org.apache.derby.iapi.services.i18n.MessageService;
36
37 import org.apache.derby.iapi.sql.compile.CompilerContext;
38
39 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
40
41 import org.apache.derby.iapi.reference.SQLState;
42
43 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
44
45 import org.apache.derby.iapi.util.JBitSet;
46
47 import org.apache.derby.catalog.AliasInfo;
48
49 import java.lang.reflect.Member JavaDoc;
50 import java.lang.reflect.Modifier JavaDoc;
51
52 import java.util.Vector JavaDoc;
53 import java.util.Enumeration JavaDoc;
54
55 /**
56  * A NewInvocationNode represents a new object() invocation.
57  *
58  * @author Jerry Brenner
59  */

60 public class NewInvocationNode extends MethodCallNode
61 {
62     // Whether or not to do a single instantiation
63
private boolean singleInstantiation = false;
64
65     private boolean delimitedIdentifier;
66
67     /**
68      * Initializer for a NewInvocationNode. Parameters are:
69      *
70      * <ul>
71      * <li>javaClassName The full package.class name of the class</li>
72      * <li>parameterList The parameter list for the constructor</li>
73      * </ul>
74      *
75      * @exception StandardException Thrown on error
76      */

77     public void init(
78                     Object JavaDoc javaClassName,
79                     Object JavaDoc params,
80                     Object JavaDoc delimitedIdentifier)
81         throws StandardException
82     {
83         super.init("<init>");
84         addParms((Vector JavaDoc) params);
85
86         this.javaClassName = (String JavaDoc) javaClassName;
87         this.delimitedIdentifier =
88                  ((Boolean JavaDoc) delimitedIdentifier).booleanValue();
89     }
90
91     /**
92      * Mark this node as only needing to
93      * to a single instantiation. (We can
94      * reuse the object after newing it.)
95      */

96     void setSingleInstantiation()
97     {
98         singleInstantiation = true;
99     }
100
101     /**
102       * Get the resolved Classes of our parameters
103       *
104       * @return the Classes of our parameters
105       */

106     public Class JavaDoc[] getMethodParameterClasses()
107     {
108         ClassInspector ci = getClassFactory().getClassInspector();
109
110         Class JavaDoc[] parmTypeClasses = new Class JavaDoc[methodParms.length];
111         for (int i = 0; i < methodParms.length; i++)
112         {
113             String JavaDoc className = methodParameterTypes[i];
114             try
115             {
116                 parmTypeClasses[i] = ci.getClass(className);
117             }
118             catch (ClassNotFoundException JavaDoc cnfe)
119             {
120                 /* We should never get this exception since we verified
121                  * that the classes existed at bind time. Just return null.
122                  */

123                 if (SanityManager.DEBUG)
124                 {
125                     SanityManager.THROWASSERT(
126                         "Unexpected exception - " + cnfe);
127                 }
128                 return null;
129             }
130         }
131
132         return parmTypeClasses;
133     }
134
135     /**
136      * Bind this expression. This means binding the sub-expressions,
137      * as well as figuring out what the return type is for this expression.
138      *
139      * @param fromList The FROM list for the query this
140      * expression is in, for binding columns.
141      * @param subqueryList The subquery list being built as we find SubqueryNodes
142      * @param aggregateVector The aggregate vector being built as we find AggregateNodes
143      *
144      * @return Nothing
145      *
146      * @exception StandardException Thrown on error
147      */

148
149     public JavaValueNode bindExpression(
150         FromList fromList, SubqueryList subqueryList,
151         Vector JavaDoc aggregateVector)
152             throws StandardException
153     {
154         bindParameters(fromList, subqueryList, aggregateVector);
155
156         javaClassName = verifyClassExist(javaClassName, !delimitedIdentifier);
157         /*
158         ** Get the parameter type names out of the parameters and put them
159         ** in an array.
160         */

161         String JavaDoc[] parmTypeNames = getObjectSignature();
162         boolean[] isParam = getIsParam();
163         ClassInspector classInspector = getClassFactory().getClassInspector();
164
165         /*
166         ** Find the matching constructor.
167         */

168         try
169         {
170             /* First try with built-in types and mappings */
171             method = classInspector.findPublicConstructor(javaClassName,
172                                             parmTypeNames, null, isParam);
173
174             /* If no match, then retry to match any possible combinations of
175              * object and primitive types.
176              */

177             if (method == null)
178             {
179                 String JavaDoc[] primParmTypeNames = getPrimitiveSignature(false);
180                 method = classInspector.findPublicConstructor(javaClassName,
181                                 parmTypeNames, primParmTypeNames, isParam);
182             }
183         }
184         catch (ClassNotFoundException JavaDoc e)
185         {
186             /*
187             ** If one of the classes couldn't be found, just act like the
188             ** method couldn't be found. The error lists all the class names,
189             ** which should give the user enough info to diagnose the problem.
190             */

191             method = null;
192         }
193
194         if (method == null)
195         {
196             /* Put the parameter type names into a single string */
197             String JavaDoc parmTypes = "";
198             for (int i = 0; i < parmTypeNames.length; i++)
199             {
200                 if (i != 0)
201                     parmTypes += ", ";
202                 parmTypes += (parmTypeNames[i].length() != 0 ?
203                                 parmTypeNames[i] :
204                                 MessageService.getTextMessage(
205                                     SQLState.LANG_UNTYPED)
206                                     );
207             }
208
209             throw StandardException.newException(SQLState.LANG_NO_CONSTRUCTOR_FOUND,
210                                                     javaClassName,
211                                                     parmTypes);
212         }
213
214         methodParameterTypes = classInspector.getParameterTypes(method);
215
216         for (int i = 0; i < methodParameterTypes.length; i++)
217         {
218             if (classInspector.primitiveType(methodParameterTypes[i]))
219                 methodParms[i].castToPrimitive(true);
220         }
221
222         /* Set type info for any null parameters */
223         if ( someParametersAreNull() )
224         {
225             setNullParameterInfo(methodParameterTypes);
226         }
227
228         /* Constructor always returns an object of type javaClassName */
229         if (SanityManager.DEBUG) {
230             SanityManager.ASSERT(javaClassName.equals(classInspector.getType(method)),
231                 "Constructor is wrong type, expected " + javaClassName +
232                 " actual is " + classInspector.getType(method));
233         }
234         setJavaTypeName( javaClassName );
235
236         return this;
237     }
238
239     /**
240      * Categorize this predicate. Initially, this means
241      * building a bit map of the referenced tables for each predicate.
242      * If the source of this ColumnReference (at the next underlying level)
243      * is not a ColumnReference or a VirtualColumnNode then this predicate
244      * will not be pushed down.
245      *
246      * For example, in:
247      * select * from (select 1 from s) a (x) where x = 1
248      * we will not push down x = 1.
249      * NOTE: It would be easy to handle the case of a constant, but if the
250      * inner SELECT returns an arbitrary expression, then we would have to copy
251      * that tree into the pushed predicate, and that tree could contain
252      * subqueries and method calls.
253      * RESOLVE - revisit this issue once we have views.
254      *
255      * @param referencedTabs JBitSet with bit map of referenced FromTables
256      * @param simplePredsOnly Whether or not to consider method
257      * calls, field references and conditional nodes
258      * when building bit map
259      *
260      * @return boolean Whether or not source.expression is a ColumnReference
261      * or a VirtualColumnNode.
262      * @exception StandardException Thrown on error
263      */

264     public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)
265         throws StandardException
266     {
267         /* We stop here when only considering simple predicates
268          * as we don't consider new opeators when looking
269          * for null invariant predicates.
270          */

271         if (simplePredsOnly)
272         {
273             return false;
274         }
275
276         boolean pushable = true;
277
278         pushable = pushable && super.categorize(referencedTabs, simplePredsOnly);
279
280         return pushable;
281     }
282
283     /**
284      * Build a JBitSet of all of the tables that we are
285      * correlated with.
286      *
287      * @param correlationMap The JBitSet of the tables that we are correlated with.
288      */

289     void getCorrelationTables(JBitSet correlationMap)
290         throws StandardException
291     {
292         CollectNodesVisitor getCRs = new CollectNodesVisitor(ColumnReference.class);
293         super.accept(getCRs);
294         Vector JavaDoc colRefs = getCRs.getList();
295         for (Enumeration JavaDoc e = colRefs.elements(); e.hasMoreElements(); )
296         {
297             ColumnReference ref = (ColumnReference)e.nextElement();
298             if (ref.getCorrelated())
299             {
300                 correlationMap.set(ref.getTableNumber());
301             }
302         }
303     }
304
305     /**
306      * Is this class assignable to the specified class?
307      * This is useful for the VTI interface where we want to see
308      * if the class implements java.sql.ResultSet.
309      *
310      * @param toClassName The java class name we want to assign to
311      *
312      * @return boolean Whether or not this class is assignable to
313      * the specified class
314      *
315      * @exception StandardException Thrown on error
316      */

317     protected boolean assignableTo(String JavaDoc toClassName) throws StandardException
318     {
319         ClassInspector classInspector = getClassFactory().getClassInspector();
320         return classInspector.assignableTo(javaClassName, toClassName);
321     }
322
323
324     /**
325      * Is this class have a public method with the specified signiture
326      * This is useful for the VTI interface where we want to see
327      * if the class has the option static method for returning the
328      * ResultSetMetaData.
329      *
330      * @param methodName The method name we are looking for
331      * @param staticMethod Whether or not the method we are looking for is static
332      *
333      * @return Member The Member representing the method (or null
334      * if the method doesn't exist).
335      *
336      * @exception StandardException Thrown on error
337      */

338     protected Member JavaDoc findPublicMethod(String JavaDoc methodName, boolean staticMethod)
339         throws StandardException
340     {
341         Member JavaDoc publicMethod;
342
343         /*
344         ** Get the parameter type names out of the parameters and put them
345         ** in an array.
346         */

347         String JavaDoc[] parmTypeNames = getObjectSignature();
348         boolean[] isParam = getIsParam();
349
350         ClassInspector classInspector = getClassFactory().getClassInspector();
351
352         try
353         {
354             publicMethod = classInspector.findPublicMethod(javaClassName, methodName,
355                                                parmTypeNames, null, isParam, staticMethod, false);
356
357             /* If no match, then retry to match any possible combinations of
358              * object and primitive types.
359              */

360             if (publicMethod == null)
361             {
362                 String JavaDoc[] primParmTypeNames = getPrimitiveSignature(false);
363                 publicMethod = classInspector.findPublicMethod(javaClassName,
364                                         methodName, parmTypeNames,
365                                         primParmTypeNames, isParam, staticMethod, false);
366             }
367         }
368         catch (ClassNotFoundException JavaDoc e)
369         {
370             /* We should always be able to find the class at this point
371              * since the protocol is to check to see if it exists
372              * before checking for a method off of it. Anyway, just return
373              * null if the class doesn't exist, since the method doesn't
374              * exist in that case.
375              */

376             if (SanityManager.DEBUG)
377             {
378                 SanityManager.THROWASSERT(
379                     "Unexpected ClassNotFoundException for javaClassName");
380             }
381             return null;
382         }
383
384         return publicMethod;
385     }
386
387     /**
388      * Do code generation for this method call
389      *
390      * @param acb The ExpressionClassBuilder for the class we're generating
391      * @param mb The method the expression will go into
392      *
393      *
394      * @exception StandardException Thrown on error
395      */

396
397     public void generateExpression(ExpressionClassBuilder acb,
398                                             MethodBuilder mb)
399                                     throws StandardException
400     {
401         /* If this node is for an ungrouped aggregator,
402          * then we generate a conditional
403          * wrapper so that we only new the aggregator once.
404          * (fx == null) ? fx = new ... : fx
405          */

406         LocalField objectFieldLF = null;
407         if (singleInstantiation)
408         {
409             /* Declare the field */
410             objectFieldLF = acb.newFieldDeclaration(Modifier.PRIVATE, javaClassName);
411
412             // now we fill in the body of the conditional
413

414             mb.getField(objectFieldLF);
415             mb.conditionalIfNull();
416         }
417
418         mb.pushNewStart(javaClassName);
419         int nargs = generateParameters(acb, mb);
420         mb.pushNewComplete(nargs);
421
422         if (singleInstantiation) {
423
424               mb.putField(objectFieldLF);
425             mb.startElseCode();
426               mb.getField(objectFieldLF);
427             mb.completeConditional();
428         }
429     }
430 }
431
Popular Tags