001package gudusoft.gsqlparser.nodes;
002/*
003 * Date: 2010-1-27
004 * Time: 11:30:12
005 */
006
007import gudusoft.gsqlparser.*;
008import gudusoft.gsqlparser.nodes.hive.THiveVariable;
009import gudusoft.gsqlparser.util.functionChecker;
010
011import java.util.HashMap;
012import java.util.Map;
013import java.util.function.Supplier;
014
015public class TNodeFactory {
016
017    // Cache of Class objects to avoid repeated lookups
018    private static final Map<Integer, Class<? extends TParseTreeNode>> NODE_TYPE_CLASSES = new HashMap<>();
019    
020    // Factory methods for frequently used node types to avoid reflection entirely
021    private static final Map<Integer, Supplier<TParseTreeNode>> NODE_FACTORIES = new HashMap<>();
022    
023    static {
024        // Pre-populate cache for all known node types
025        // for (ENodeType nodeType : ENodeType.values()) {
026        //     try {
027        //         NODE_TYPE_CLASSES.put(nodeType.getId(), 
028        //             (Class<? extends TParseTreeNode>) Class.forName(nodeType.toString()));
029        //     } catch (ClassNotFoundException e) {
030        //         // Log error but continue - handle during runtime if needed
031        //         System.out.println("Failed to preload class for node type: " + nodeType + ": " + e.getMessage());
032        //     }
033        // }
034        
035        // Add specialized factory methods for common node types
036        NODE_FACTORIES.put(ENodeType.T_Expression.getId(), () -> new TExpression());
037        NODE_FACTORIES.put(ENodeType.T_FunctionCall.getId(), () -> new TFunctionCall());
038        NODE_FACTORIES.put(ENodeType.T_SelectSqlNode.getId(), () -> new TSelectSqlNode());
039        NODE_FACTORIES.put(ENodeType.T_WhereClause.getId(), () -> new TWhereClause());
040        NODE_FACTORIES.put(ENodeType.T_Constant.getId(), () -> new TConstant());
041        NODE_FACTORIES.put(ENodeType.T_ObjectName.getId(), () -> new TObjectName());
042        NODE_FACTORIES.put(ENodeType.T_TableReference.getId(), () -> new TTableReference());
043        NODE_FACTORIES.put(ENodeType.T_ColumnReference.getId(), () -> new TColumnReference());
044        NODE_FACTORIES.put(ENodeType.T_CreateTableSqlNode.getId(), () -> new TCreateTableSqlNode());
045    }
046
047    public TNodeFactory(){
048    }
049
050    public TNodeFactory(EDbVendor dbVendor){
051        this.dbVendor = dbVendor;
052    }
053
054    public EDbVendor getDbVendor() {
055        return dbVendor;
056    }
057
058
059    private EDbVendor dbVendor = EDbVendor.dbvgeneric;
060
061    public void setGsqlParser(TGSqlParser parser) {
062        this.gsqlparser = parser;
063    }
064
065    private TGSqlParser gsqlparser = null;
066
067    public TColumnReference createColumnReference(TObjectName objectname){
068        TColumnReference retval = (TColumnReference)createNode(ENodeType.T_ColumnReference.getId(),objectname);
069        return retval;
070    }
071
072    public TColumnReference createColumnReference(TSourceToken objectname){
073        TColumnReference retval = (TColumnReference)createNode(ENodeType.T_ColumnReference.getId(),objectname);
074        return retval;
075    }
076
077    public TTableReference createTableReference(TObjectName objectname){
078        TTableReference retval = (TTableReference)createNode(ENodeType.T_TableReference.getId(),objectname);
079        return retval;
080    }
081
082    public TObjectReference createObjectReference(TObjectName objectname, int objecttype){
083        TObjectReference retval = (TObjectReference)createNode(ENodeType.T_ObjectReference.getId(),objectname);
084        retval.setObjectType(objecttype);
085        return retval;
086    }
087
088    public TParseTreeNode createIntervalExpression(){
089        TIntervalExpression retval = (TIntervalExpression)createNode(ENodeType.T_IntervalExression.getId());
090        return retval;
091    }
092
093    public TParseTreeNode createDatetimeExpression(){
094        TDatetimeExpression retval = (TDatetimeExpression)createNode(ENodeType.T_DatetimeExression.getId());
095        return retval;
096    }
097
098    public TParseTreeNode createFunctionCall(EFunctionType eFunctionType, TObjectName functionName){
099        TFunctionCall retval = (TFunctionCall)createNode(ENodeType.T_FunctionCall.getId(),functionName,eFunctionType);
100     //   functionName.parseFunctionName();
101        return retval;
102    }
103
104    public TParseTreeNode createSelectSqlNode(){
105        TSelectSqlNode retval = (TSelectSqlNode)createNode(ENodeType.T_SelectSqlNode.getId());
106        return retval;
107    }
108    
109
110
111    public TParseTreeNode createExpression(EExpressionType operatorType){
112        TExpression retval = (TExpression)createNode(ENodeType.T_Expression.getId(),operatorType);
113        //retval.setExpressionType(operatorType);
114        //retval.setExprType(operatorType);
115        return retval;
116    }
117
118    public TParseTreeNode createExpression(EExpressionType operatorType,TExpression leftOperand,TExpression rightOperand){
119        TExpression retval = (TExpression)createNode(ENodeType.T_Expression.getId(),operatorType);
120        //retval.setExpressionType(operatorType);
121        //retval.setExprType(operatorType);
122        retval.setLeftOperand(leftOperand);
123        retval.setRightOperand(rightOperand);
124        return retval;
125    }
126
127    public TParseTreeNode createCompoundExpression(EExpressionType operatorType,TExpression leftOperand,TExpression rightOperand ){
128        EExpressionType lcOperatorType = operatorType;
129        if (lcOperatorType == EExpressionType.group_comparison_t){
130            if (leftOperand.getExpressionType() == EExpressionType.list_t){
131
132            }else{
133                lcOperatorType = EExpressionType.simple_comparison_t;
134            }
135        }
136       TExpression retval = (TExpression)createNode(ENodeType.T_Expression.getId(),lcOperatorType);
137        //retval.setExpressionType(operatorType);
138        //retval.setExprType(operatorType);
139        retval.setLeftOperand(leftOperand);
140        retval.setRightOperand(rightOperand);
141        return retval;
142    }
143
144    public TExpression createSimpleExpression(TObjectName or){
145       boolean isOracleDBMS_package_call = false;
146        TExpression retval;
147
148        if ((dbVendor == EDbVendor.dbvoracle) && (or.getNumberOfPart() == 2)){
149           // 检查是否为oracle DBMS_ package, 如果是的话,需要转为function_t, 而不是simple_object_name_t
150            isOracleDBMS_package_call = functionChecker.isOraclePredefinedPackageFunction(or.toString());
151       }
152        if (isOracleDBMS_package_call){
153            retval = (TExpression)createNode(ENodeType.T_Expression.getId(),EExpressionType.function_t);
154            retval.setFunctionCall((TFunctionCall) this.createFunctionCall(EFunctionType.oracle_dbms_package_t,or));
155        }else{
156            retval = (TExpression)createNode(ENodeType.T_Expression.getId(),EExpressionType.simple_object_name_t);
157            retval.setObjectOperand(or);
158        }
159
160        //retval.setExpressionType(TExpression.simpleObjectname);
161        //retval.setExprType(EExpressionType.simple_object_name_t);
162
163        retval.setStartToken(or);
164        retval.setEndToken(or);
165        return retval;
166    }
167
168    public TObjectName createObjectNameWithType(EDbObjectType dbObjectType, TSourceToken part) {
169        if ((part == null)) return null;
170        TObjectName retval = (TObjectName)createNode(ENodeType.T_ObjectName.getId(),dbObjectType,part);
171        retval.setStartToken(part);
172        retval.setEndToken(part);
173        return retval;
174    }
175
176    public TObjectName createObjectNameWithType(EDbObjectType dbObjectType, TSourceToken object,TSourceToken part) {
177        if ((object == null)&&(part == null)) return null;
178        TObjectName retval = (TObjectName)createNode(ENodeType.T_ObjectName.getId(),dbObjectType,object,part);
179
180        if (part != null){
181            retval.setEndToken(part);
182        }else {
183            if(object != null){
184                retval.setEndToken(object);
185            } else {
186            }
187        }
188
189
190        if(object != null){
191            retval.setStartToken(object);
192        } else {
193            if(part != null){
194                retval.setStartToken(part);
195            }
196        }
197
198        return retval;
199    }
200
201    public TObjectName createObjectNameWithType(EDbObjectType dbObjectType, TSourceToken schema,TSourceToken object,TSourceToken part) {
202        if ((object == null)&&(part == null)) return null;
203        TObjectName retval = (TObjectName)createNode(ENodeType.T_ObjectName.getId(),dbObjectType,schema,object,part);
204        retval.setStartToken(schema);
205        retval.setEndToken(part);
206
207        return retval;
208    }
209
210    public TObjectName createObjectName(EDbObjectType dbObjectType, TSourceToken schema,TSourceToken object,TSourceToken part){
211        if ((schema == null)&&(object == null)&&(part == null)) return null;
212        TObjectName retval = (TObjectName)createNode(ENodeType.T_ObjectName.getId(),dbObjectType,schema,object,part);
213
214        if (part != null){
215            retval.setEndToken(part);
216        }else {
217            if(object != null){
218                retval.setEndToken(object);
219            } else {
220                if(schema != null){
221                    retval.setEndToken(schema);
222                }
223            }
224        }
225
226        if (schema != null){
227            retval.setStartToken(schema);
228        }else {
229            if(object != null){
230                retval.setStartToken(object);
231            } else {
232                if(part != null){
233                    retval.setStartToken(part);
234                }
235            }
236        }
237
238        return retval;
239
240    }
241
242    /**
243     *  create a database object with schema, object and part name, type of this object will be
244     *  determined later in the context where it appears.
245     * @param schema schema name of this object.
246     * @param object object name such as table, view, function and etc.
247     * @param part part of object, depends on object, if object is table, then part will be column name; will be null if object is function
248     * @return
249     */
250    public TObjectName createObjectName(TSourceToken schema,TSourceToken object,TSourceToken part){
251        if ((schema == null)&&(object == null)&&(part == null)) return null;
252        TObjectName retval = (TObjectName)createNode(ENodeType.T_ObjectName.getId(),schema,object,part);
253
254        if (part != null){
255            retval.setEndToken(part);
256        }else {
257            if(object != null){
258                retval.setEndToken(object);
259            } else {
260                if(schema != null){
261                    retval.setEndToken(schema);
262                }
263            }
264        }
265
266        if (schema != null){
267            retval.setStartToken(schema);
268        }else {
269            if(object != null){
270                retval.setStartToken(object);
271            } else {
272                if(part != null){
273                    retval.setStartToken(part);
274                }
275            }
276        }
277
278        return retval;
279    }
280
281    public TObjectName createObjectNameWithPart(TSourceToken part){
282        return createObjectName(null,null,part);
283    }
284
285    public TObjectName createObjectNameWithObject(TSourceToken object){
286        return createObjectName(null,object,null);
287    }
288
289    public TObjectName createObjectNameWithPartAndObject(TSourceToken object,TSourceToken part){
290        return createObjectName(null,object,part);
291    }
292
293    public TParseTreeNode createSimpleExpression(TConstant cnt){
294        if (cnt.getLiteralType() == ELiteralType.etFakeDate){
295
296            TFunctionCall functionCall = (TFunctionCall)createFunctionCall(EFunctionType.date_t,TObjectName.createObjectName ( this.dbVendor, EDbObjectType.function,cnt.getStartToken()));
297            TExpression expression = (TExpression)createExpression(EExpressionType.function_t);
298            expression.setFunctionCall(functionCall);
299            expression.setStartToken(functionCall.getStartToken());
300            expression.setEndToken(functionCall.getEndToken());
301            return expression;
302
303        }else{
304            TExpression retval = (TExpression)createNode(ENodeType.T_Expression.getId(),EExpressionType.simple_constant_t);
305            //retval.setExpressionType(TExpression.simpleConstant);
306            //retval.setExprType(EExpressionType.simple_constant_t);
307            retval.setConstantOperand(cnt);
308            retval.setStartToken(cnt.getStartToken());
309            retval.setEndToken(cnt.getEndToken());
310            return retval;
311        }
312    }
313
314    public TParseTreeNode createSimpleExpression(TSourceToken st){
315       TExpression retval = (TExpression)createNode(ENodeType.T_Expression.getId(),EExpressionType.simple_source_token_t);
316       //retval.setExpressionType(TExpression.simpleSourcetoken);
317       //retval.setExprType(EExpressionType.simple_source_token_t);
318       retval.setSourcetokenOperand(st);
319        retval.setStartToken(st);
320        retval.setObjectOperand(createObjectNameWithPart(st));
321        retval.setEndToken(st);
322       return retval;
323    }
324
325    public TParseTreeNode createSimpleExpression(THiveVariable variable){
326       TExpression retval = (TExpression)createNode(ENodeType.T_Expression.getId(),EExpressionType.hive_variable_t);
327       retval.setHive_variable(variable);
328        retval.setStartToken(variable);
329        retval.setEndToken(variable);
330       return retval;
331    }
332
333    private ELiteralType getETByNT(ENodeType ent){
334        ELiteralType et = ELiteralType.etString;
335        switch (ent){
336            case T_Constant:
337                et = ELiteralType.etString;
338                break;
339            case T_Constant_Double:
340            case T_Constant_Float:
341                et = ELiteralType.etFloat;
342                break;
343            case T_Constant_Integer:
344                et = ELiteralType.etNumber;
345                break;
346            case T_Constant_String:
347                et = ELiteralType.etString;
348                break;
349            case T_Constant_BindV:
350                break;
351            case T_Constant_Boolean:
352                et = ELiteralType.bool;
353                break;
354            case T_Constant_Date:
355                et = ELiteralType.datetime_date;
356                break;
357            case T_Constant_Interval:
358                et = ELiteralType.interval;
359                break;
360            case T_Constant_Null:
361                et = ELiteralType.character_string;
362                break;
363            case T_Constant_Time:
364                et = ELiteralType.datetime_time;
365                break;
366            case T_Constant_Timestamp:
367                et = ELiteralType.datetime_timestamp;
368                break;
369            default:
370                break;
371        }
372        return et;
373    }
374    public TParseTreeNode createConstant(TSourceToken st,ENodeType ent){
375         TConstant retval = (TConstant)createNode(ENodeType.T_Constant.getId(),getETByNT(ent)); //(TConstant) createNode(ent.getId());
376         retval.setStartToken(st);
377         retval.setEndToken(st);
378         retval.setValueToken(st);
379         return retval;
380    }
381
382//    public TParseTreeNode createConstant(TParseTreeNode node,ENodeType ent){
383//         TConstant retval = (TConstant)createNode(ENodeType.T_Constant.getId(),getETByNT(ent));//(TConstant) createNode(ent.getId());
384//        retval.setStartToken(node);
385//        retval.setEndToken(node);
386//         return retval;
387//    }
388
389    private Class<? extends TParseTreeNode> getNodeClass(int nodeType) {
390        return NODE_TYPE_CLASSES.computeIfAbsent(nodeType, id -> {
391            try {
392                ENodeType type = ENodeType.fromId(id);
393                return type != null ? 
394                    (Class<? extends TParseTreeNode>) Class.forName(type.toString()) : null;
395            } catch (ClassNotFoundException e) {
396                return null;
397            }
398        });
399    }
400
401    /**
402     * Get a node that takes no initializer arguments.
403     *
404     * @param nodeType          Identifier for the type of node.
405     *
406     * @return  A new ParseTree node.
407     */
408    public TParseTreeNode createNode(int nodeType) {
409        TParseTreeNode retval = null;
410        
411        // First check for a specialized factory method
412        Supplier<TParseTreeNode> factory = NODE_FACTORIES.get(nodeType);
413        if (factory != null) {
414            // Use direct instantiation without reflection
415            retval = factory.get();
416        } else {
417            // Get from class cache
418            Class<? extends TParseTreeNode> nodeClass = getNodeClass(nodeType);// NODE_TYPE_CLASSES.get(nodeType);
419            
420            // If not found in cache, try to load it dynamically
421            if (nodeClass == null) {
422                String nodeName = nodeName(nodeType);
423                try {
424                    nodeClass = (Class<? extends TParseTreeNode>) Class.forName(nodeName);
425                    // Store in cache for future use
426                    NODE_TYPE_CLASSES.put(nodeType, nodeClass);
427                } catch (ClassNotFoundException cnfe) {
428                    System.out.println(cnfe.toString()+", nodename: "+nodeName);
429                    return null;
430                }
431            }
432
433            try {
434                retval = nodeClass.newInstance();
435            } catch (Exception iae) {
436                System.out.println(iae.toString()+", nodeType: "+nodeType);
437                return null;
438            }
439        }
440
441        retval.setNodeType(nodeType);
442        if (nodeType != 25) {
443            // T_Typename(25,"gudusoft.gsqlparser.nodes.TTypeName"),
444            // don't sqlparser instance to a ttypename to avoid memory leak
445            retval.setGsqlparser(this.gsqlparser);
446        }
447        if ((retval.dbvendor == EDbVendor.dbvgeneric) && (this.dbVendor != EDbVendor.dbvgeneric)){
448            // not already set in retval.setGsqlparser(this.gsqlparser);
449            retval.dbvendor = this.dbVendor;
450        }
451
452        return retval;
453    }
454
455    public <T>  TPTNodeList<T> createPTNodeList(T c) {
456        int nodeType = ENodeType.T_PTNodeList.getId(); // T_PTNodeList(14,"gudusoft.gsqlparser.nodes.TPTNodeList"),
457        TPTNodeList<T> retval = new gudusoft.gsqlparser.nodes.TPTNodeList<T>();
458        retval.setNodeType(nodeType);
459        retval.setGsqlparser(this.gsqlparser);
460        retval.init(c);
461        return retval;
462    }
463
464
465    /**
466     * Translate a node type to a class name
467     *
468     * @param nodeType  A node type identifier 
469     *
470     */
471    protected String nodeName(int nodeType)
472    {
473       return ENodeType.fromId(nodeType).toString();
474    }
475
476    /**
477     * Get a node that takes one initializer argument.
478     *
479     * @param nodeType          Identifier for the type of node.
480     * @param arg1      The initializer argument
481     *
482     * @return  A new ParseTree node.
483     *
484     */
485    public final TParseTreeNode createNode(int nodeType, Object arg1)
486    {
487        TParseTreeNode retval = createNode(nodeType);
488
489        retval.init(arg1);
490
491        return  retval;
492    }
493
494    /**
495     * Get a node that takes one initializer argument.
496     *
497     * @param nodeType          Identifier for the type of node.
498     * @param arg1      The initializer argument
499     * @param arg2      The initializer argument
500     *
501     * @return  A new ParseTreeNode node.
502     *
503     */
504    public final TParseTreeNode createNode(int nodeType, Object arg1, Object arg2)
505    {
506        TParseTreeNode retval = createNode(nodeType);
507
508        retval.init(arg1,arg2);
509
510        return  retval;
511    }
512
513    /**
514     * Get a node that takes one initializer argument.
515     *
516     * @param nodeType          Identifier for the type of node.
517     * @param arg1      The initializer argument
518     * @param arg2      The initializer argument
519     * @param arg3      The initializer argument
520     *
521     * @return  A new ParseTreeNode node.
522     *
523     */
524    public final TParseTreeNode createNode(int nodeType, Object arg1, Object arg2, Object arg3)
525    {
526        TParseTreeNode retval = createNode(nodeType);
527
528        retval.init(arg1,arg2,arg3);
529
530        return  retval;
531    }
532
533    public final TParseTreeNode createNode(int nodeType, Object arg1, Object arg2, Object arg3, Object arg4)
534    {
535        TParseTreeNode retval = createNode(nodeType);
536
537        retval.init(arg1,arg2,arg3,arg4);
538
539        return  retval;
540    }
541
542    public final TParseTreeNode createNode(int nodeType, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
543    {
544        TParseTreeNode retval = createNode(nodeType);
545
546        retval.init(arg1,arg2,arg3,arg4,arg5);
547
548        return  retval;
549    }
550
551    public final TParseTreeNode createNode(int nodeType, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6)
552    {
553        TParseTreeNode retval = createNode(nodeType);
554
555        retval.init(arg1,arg2,arg3,arg4,arg5,arg6);
556
557        return  retval;
558    }
559
560
561}