001
002package gudusoft.gsqlparser.pp.stmtformatter;
003
004import gudusoft.gsqlparser.TCustomSqlStatement;
005import gudusoft.gsqlparser.TGSqlParser;
006import gudusoft.gsqlparser.TSourceToken;
007import gudusoft.gsqlparser.TSourceTokenList;
008import gudusoft.gsqlparser.TStatementList;
009import gudusoft.gsqlparser.pp.mediator.MediatorFactory;
010import gudusoft.gsqlparser.pp.output.OutputConfig;
011import gudusoft.gsqlparser.pp.output.OutputConfigFactory;
012import gudusoft.gsqlparser.pp.para.GFmtOpt;
013import gudusoft.gsqlparser.pp.para.styleenums.TCompactMode;
014import gudusoft.gsqlparser.pp.print.IPrinter;
015import gudusoft.gsqlparser.pp.print.PrinterFactory;
016import gudusoft.gsqlparser.pp.processor.ProcessorFactory;
017import gudusoft.gsqlparser.pp.stmtformatter.builder.AbstractStmtFormatterBuilder;
018import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.AllStmtsFormatterBuilder;
019import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.AlterTableStmtFormatterBuilder;
020import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.CommonStmtFormatterBuilder;
021import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.CompactModeStmtFormatterBuilder;
022import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.CreateTableStmtFormatterBuilder;
023import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.CreateViewStmtFormatterBuilder;
024import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.DeclareStmtFormatterBuilder;
025import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.DeleteStmtFormatterBuilder;
026import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.ExecuteStmtFormatterBuilder;
027import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.GoStmtFormatterBuilder;
028import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.IfStmtFormatterBuilder;
029import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.InsertStmtFormatterBuilder;
030import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.MergeStmtFormatterBuilder;
031import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.PlsqlBlockStmtFormatterBuilder;
032import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.PlsqlIfStmtFormatterBuilder;
033import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.PlsqlStmtFormatterBuilder;
034import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.ReturnStmtFormatterBuilder;
035import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.SelectStmtFormatterBuilder;
036import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.SetStmtFormatterBuilder;
037import gudusoft.gsqlparser.pp.stmtformatter.builder.comm.UpdateStmtFormatterBuilder;
038import gudusoft.gsqlparser.pp.stmtformatter.type.AbstractStmtFormatter;
039import gudusoft.gsqlparser.pp.stmtformatter.type.comm.AllStmtsFormatter;
040import gudusoft.gsqlparser.pp.stmtformatter.type.comm.AlterTableStmtFormatter;
041import gudusoft.gsqlparser.pp.stmtformatter.type.comm.CommonStmtFormatter;
042import gudusoft.gsqlparser.pp.stmtformatter.type.comm.CompactModeStmtFormatter;
043import gudusoft.gsqlparser.pp.stmtformatter.type.comm.CreateTableStmtFormatter;
044import gudusoft.gsqlparser.pp.stmtformatter.type.comm.CreateViewStmtFormatter;
045import gudusoft.gsqlparser.pp.stmtformatter.type.comm.DeclareStmtFormatter;
046import gudusoft.gsqlparser.pp.stmtformatter.type.comm.DeleteStmtFormatter;
047import gudusoft.gsqlparser.pp.stmtformatter.type.comm.ExecuteStmtFormatter;
048import gudusoft.gsqlparser.pp.stmtformatter.type.comm.GoStmtFormatter;
049import gudusoft.gsqlparser.pp.stmtformatter.type.comm.IfStmtFormatter;
050import gudusoft.gsqlparser.pp.stmtformatter.type.comm.InsertStmtFormatter;
051import gudusoft.gsqlparser.pp.stmtformatter.type.comm.MergeStmtFormatter;
052import gudusoft.gsqlparser.pp.stmtformatter.type.comm.PlsqlBlockStmtFormatter;
053import gudusoft.gsqlparser.pp.stmtformatter.type.comm.PlsqlIfStmtFormatter;
054import gudusoft.gsqlparser.pp.stmtformatter.type.comm.PlsqlStmtFormatter;
055import gudusoft.gsqlparser.pp.stmtformatter.type.comm.ReturnStmtFormatter;
056import gudusoft.gsqlparser.pp.stmtformatter.type.comm.SelectStmtFormatter;
057import gudusoft.gsqlparser.pp.stmtformatter.type.comm.SetStmtFormatter;
058import gudusoft.gsqlparser.pp.stmtformatter.type.comm.UpdateStmtFormatter;
059import gudusoft.gsqlparser.pp.utils.SourceTokenOperator;
060import gudusoft.gsqlparser.stmt.TAlterTableStatement;
061import gudusoft.gsqlparser.stmt.TCommonBlock;
062import gudusoft.gsqlparser.stmt.TCreateTableSqlStatement;
063import gudusoft.gsqlparser.stmt.TCreateViewSqlStatement;
064import gudusoft.gsqlparser.stmt.TDeleteSqlStatement;
065import gudusoft.gsqlparser.stmt.TIfStmt;
066import gudusoft.gsqlparser.stmt.TInsertSqlStatement;
067import gudusoft.gsqlparser.stmt.TMergeSqlStatement;
068import gudusoft.gsqlparser.stmt.TSelectSqlStatement;
069import gudusoft.gsqlparser.stmt.TStoredProcedureSqlStatement;
070import gudusoft.gsqlparser.stmt.TUpdateSqlStatement;
071import gudusoft.gsqlparser.stmt.mssql.TMssqlBlock;
072import gudusoft.gsqlparser.stmt.mssql.TMssqlDeclare;
073import gudusoft.gsqlparser.stmt.mssql.TMssqlExecute;
074import gudusoft.gsqlparser.stmt.mssql.TMssqlGo;
075import gudusoft.gsqlparser.stmt.mssql.TMssqlIfElse;
076import gudusoft.gsqlparser.stmt.mssql.TMssqlReturn;
077import gudusoft.gsqlparser.stmt.mssql.TMssqlSet;
078import gudusoft.gsqlparser.pp2.Pp2FormatOptions;
079import gudusoft.gsqlparser.pp2.Pp2FormatResult;
080import gudusoft.gsqlparser.pp2.engine.Pp2Engine;
081
082import java.io.ByteArrayOutputStream;
083import java.io.OutputStream;
084import java.util.ArrayList;
085import java.util.List;
086import java.util.Map;
087import java.util.concurrent.ConcurrentHashMap;
088
089public class FormatterFactory
090{
091
092        /**
093         * all formatters
094         */
095        private volatile static Map<String, AbstractStmtFormatter> formatter = new ConcurrentHashMap<String, AbstractStmtFormatter>( );
096
097        private static Object object = new Object( );
098
099        private static OutputConfig outputConfig;
100
101        /**
102         * create select statment formatter
103         * 
104         * @param opt
105         *            options
106         * @return instance
107         */
108        public static SelectStmtFormatter createSelectStmtFormatter( GFmtOpt opt )
109        {
110                return createFormatter( opt,
111                                SelectStmtFormatter.class,
112                                new IFormatterBuilderCreator<SelectStmtFormatter>( ) {
113
114                                        public AbstractStmtFormatterBuilder<SelectStmtFormatter> create( )
115                                        {
116                                                return new SelectStmtFormatterBuilder( );
117                                        }
118                                } );
119        }
120
121        public static InsertStmtFormatter createInsertStmtFormatter( GFmtOpt opt )
122        {
123                return createFormatter( opt,
124                                InsertStmtFormatter.class,
125                                new IFormatterBuilderCreator<InsertStmtFormatter>( ) {
126
127                                        public AbstractStmtFormatterBuilder<InsertStmtFormatter> create( )
128                                        {
129                                                return new InsertStmtFormatterBuilder( );
130                                        }
131                                } );
132        }
133
134        public static DeleteStmtFormatter createDeleteStmtFormatter( GFmtOpt opt )
135        {
136                return createFormatter( opt,
137                                DeleteStmtFormatter.class,
138                                new IFormatterBuilderCreator<DeleteStmtFormatter>( ) {
139
140                                        public AbstractStmtFormatterBuilder<DeleteStmtFormatter> create( )
141                                        {
142                                                return new DeleteStmtFormatterBuilder( );
143                                        }
144                                } );
145        }
146
147        public static UpdateStmtFormatter createUpdateStmtFormatter( GFmtOpt opt )
148        {
149                return createFormatter( opt,
150                                UpdateStmtFormatter.class,
151                                new IFormatterBuilderCreator<UpdateStmtFormatter>( ) {
152
153                                        public AbstractStmtFormatterBuilder<UpdateStmtFormatter> create( )
154                                        {
155                                                return new UpdateStmtFormatterBuilder( );
156                                        }
157                                } );
158        }
159
160        public static CreateTableStmtFormatter createCreateTableStmtFormatter(
161                        GFmtOpt opt )
162        {
163                return createFormatter( opt,
164                                CreateTableStmtFormatter.class,
165                                new IFormatterBuilderCreator<CreateTableStmtFormatter>( ) {
166
167                                        public AbstractStmtFormatterBuilder<CreateTableStmtFormatter> create( )
168                                        {
169                                                return new CreateTableStmtFormatterBuilder( );
170                                        }
171                                } );
172        }
173
174        public static DeclareStmtFormatter createDeclareStmtFormatter( GFmtOpt opt )
175        {
176                return createFormatter( opt,
177                                DeclareStmtFormatter.class,
178                                new IFormatterBuilderCreator<DeclareStmtFormatter>( ) {
179
180                                        public AbstractStmtFormatterBuilder<DeclareStmtFormatter> create( )
181                                        {
182                                                return new DeclareStmtFormatterBuilder( );
183                                        }
184                                } );
185        }
186
187        public static ExecuteStmtFormatter createExecuteStmtFormatter( GFmtOpt opt )
188        {
189                return createFormatter( opt,
190                                ExecuteStmtFormatter.class,
191                                new IFormatterBuilderCreator<ExecuteStmtFormatter>( ) {
192
193                                        public AbstractStmtFormatterBuilder<ExecuteStmtFormatter> create( )
194                                        {
195                                                return new ExecuteStmtFormatterBuilder( );
196                                        }
197                                } );
198        }
199
200        public static SetStmtFormatter createSetStmtFormatter( GFmtOpt opt )
201        {
202                return createFormatter( opt,
203                                SetStmtFormatter.class,
204                                new IFormatterBuilderCreator<SetStmtFormatter>( ) {
205
206                                        public AbstractStmtFormatterBuilder<SetStmtFormatter> create( )
207                                        {
208                                                return new SetStmtFormatterBuilder( );
209                                        }
210                                } );
211        }
212
213        public static IfStmtFormatter createIfStmtFormatter( GFmtOpt opt )
214        {
215                return createFormatter( opt,
216                                IfStmtFormatter.class,
217                                new IFormatterBuilderCreator<IfStmtFormatter>( ) {
218
219                                        public AbstractStmtFormatterBuilder<IfStmtFormatter> create( )
220                                        {
221                                                return new IfStmtFormatterBuilder( );
222                                        }
223                                } );
224        }
225
226        public static PlsqlIfStmtFormatter createPlsqlIfStmtFormatter( GFmtOpt opt )
227        {
228                return createFormatter( opt,
229                                PlsqlIfStmtFormatter.class,
230                                new IFormatterBuilderCreator<PlsqlIfStmtFormatter>( ) {
231
232                                        public AbstractStmtFormatterBuilder<PlsqlIfStmtFormatter> create( )
233                                        {
234                                                return new PlsqlIfStmtFormatterBuilder( );
235                                        }
236                                } );
237        }
238
239        public static PlsqlStmtFormatter createPlsqlStmtFormatter( GFmtOpt opt )
240        {
241                return createFormatter( opt,
242                                PlsqlStmtFormatter.class,
243                                new IFormatterBuilderCreator<PlsqlStmtFormatter>( ) {
244
245                                        public AbstractStmtFormatterBuilder<PlsqlStmtFormatter> create( )
246                                        {
247                                                return new PlsqlStmtFormatterBuilder( );
248                                        }
249                                } );
250        }
251
252        public static GoStmtFormatter createGoStmtFormatter( GFmtOpt opt )
253        {
254                return createFormatter( opt,
255                                GoStmtFormatter.class,
256                                new IFormatterBuilderCreator<GoStmtFormatter>( ) {
257
258                                        public AbstractStmtFormatterBuilder<GoStmtFormatter> create( )
259                                        {
260                                                return new GoStmtFormatterBuilder( );
261                                        }
262                                } );
263        }
264
265        public static CompactModeStmtFormatter createCompactModeStmtFormatter(
266                        GFmtOpt opt )
267        {
268                return createFormatter( opt,
269                                CompactModeStmtFormatter.class,
270                                new IFormatterBuilderCreator<CompactModeStmtFormatter>( ) {
271
272                                        public AbstractStmtFormatterBuilder<CompactModeStmtFormatter> create( )
273                                        {
274                                                return new CompactModeStmtFormatterBuilder( );
275                                        }
276                                } );
277        }
278
279        public static ReturnStmtFormatter createReturnStmtFormatter( GFmtOpt opt )
280        {
281                return createFormatter( opt,
282                                ReturnStmtFormatter.class,
283                                new IFormatterBuilderCreator<ReturnStmtFormatter>( ) {
284
285                                        public AbstractStmtFormatterBuilder<ReturnStmtFormatter> create( )
286                                        {
287                                                return new ReturnStmtFormatterBuilder( );
288                                        }
289                                } );
290        }
291
292        public static CreateViewStmtFormatter createCreateViewStmtFormatter(
293                        GFmtOpt opt )
294        {
295                return createFormatter( opt,
296                                CreateViewStmtFormatter.class,
297                                new IFormatterBuilderCreator<CreateViewStmtFormatter>( ) {
298
299                                        public AbstractStmtFormatterBuilder<CreateViewStmtFormatter> create( )
300                                        {
301                                                return new CreateViewStmtFormatterBuilder( );
302                                        }
303                                } );
304        }
305
306        public static AlterTableStmtFormatter createAlterTableStatement( GFmtOpt opt )
307        {
308                return createFormatter( opt,
309                                AlterTableStmtFormatter.class,
310                                new IFormatterBuilderCreator<AlterTableStmtFormatter>( ) {
311
312                                        public AbstractStmtFormatterBuilder<AlterTableStmtFormatter> create( )
313                                        {
314                                                return new AlterTableStmtFormatterBuilder( );
315                                        }
316                                } );
317        }
318
319        /**
320         * the callback interface to achieve the formatter builder
321         * 
322         * @author zhoujun
323         * 
324         */
325        public interface IFormatterBuilderCreator<E extends AbstractStmtFormatter>
326        {
327
328                AbstractStmtFormatterBuilder<E> create( );
329        }
330
331        /**
332         * create the formatter
333         * 
334         * @param <E>
335         * @param opt
336         * @param clazz
337         * @param creater
338         * @return
339         */
340        public static <E extends AbstractStmtFormatter> E createFormatter(
341                        GFmtOpt opt, Class<E> clazz, IFormatterBuilderCreator<E> creater )
342        {
343                String id = opt.sessionId + clazz.getName( );
344                if ( !formatter.containsKey( id ) )
345                {
346                        synchronized ( FormatterFactory.class )
347                        {
348                                if ( !formatter.containsKey( id ) )
349                                {
350                                        AbstractStmtFormatterBuilder builder = creater.create( );
351                                        builder.setOption( opt );
352                                        formatter.put( id, builder.build( ) );
353                                }
354                        }
355                }
356                return (E) formatter.get( id );
357        }
358
359        public static void processStatement( GFmtOpt option, TCustomSqlStatement sql )
360        {
361                if ( option.compactMode == TCompactMode.Cpmugly )
362                {
363                        FormatterFactory.createCompactModeStmtFormatter( option )
364                                        .format( sql );
365                        return;
366                }
367
368                if ( isNotNeedFormat( sql ) )
369                {
370                        return;
371                }
372                if ( sql instanceof TSelectSqlStatement )
373                {
374                        FormatterFactory.createSelectStmtFormatter( option )
375                                        .format( (TSelectSqlStatement) sql );
376                }
377                else if ( sql instanceof TInsertSqlStatement )
378                {
379                        FormatterFactory.createInsertStmtFormatter( option )
380                                        .format( (TInsertSqlStatement) sql );
381                }
382                else if ( sql instanceof TDeleteSqlStatement )
383                {
384                        FormatterFactory.createDeleteStmtFormatter( option )
385                                        .format( (TDeleteSqlStatement) sql );
386                }
387                else if ( sql instanceof TUpdateSqlStatement )
388                {
389                        FormatterFactory.createUpdateStmtFormatter( option )
390                                        .format( (TUpdateSqlStatement) sql );
391                }
392                else if ( sql instanceof TCreateTableSqlStatement )
393                {
394                        FormatterFactory.createCreateTableStmtFormatter( option )
395                                        .format( (TCreateTableSqlStatement) sql );
396                }
397                else if ( sql instanceof TMssqlDeclare )
398                {
399                        FormatterFactory.createDeclareStmtFormatter( option )
400                                        .format( (TMssqlDeclare) sql );
401                }
402                else if ( sql instanceof TMssqlExecute )
403                {
404                        FormatterFactory.createExecuteStmtFormatter( option )
405                                        .format( (TMssqlExecute) sql );
406                }
407                else if ( sql instanceof TStoredProcedureSqlStatement )
408                {
409                        FormatterFactory.createPlsqlStmtFormatter( option )
410                                        .format( (TStoredProcedureSqlStatement) sql );
411                }
412                else if ( sql instanceof TMssqlSet )
413                {
414                        FormatterFactory.createSetStmtFormatter( option )
415                                        .format( (TMssqlSet) sql );
416                }
417                else if ( sql instanceof TMssqlIfElse )
418                {
419                        FormatterFactory.createIfStmtFormatter( option )
420                                        .format( (TMssqlIfElse) sql );
421                }
422                else if ( sql instanceof TMssqlGo )
423                {
424                        FormatterFactory.createGoStmtFormatter( option )
425                                        .format( (TMssqlGo) sql );
426                }
427                else if ( sql instanceof TMssqlReturn )
428                {
429                        FormatterFactory.createReturnStmtFormatter( option )
430                                        .format( (TMssqlReturn) sql );
431                }
432                else if ( sql instanceof TCreateViewSqlStatement )
433                {
434                        FormatterFactory.createCreateViewStmtFormatter( option )
435                                        .format( (TCreateViewSqlStatement) sql );
436                }
437                else if ( sql instanceof TAlterTableStatement )
438                {
439                        FormatterFactory.createAlterTableStatement( option )
440                                        .format( (TAlterTableStatement) sql );
441                }
442                else if ( sql instanceof TMergeSqlStatement )
443                {
444                        FormatterFactory.createMergeSqlStatement( option )
445                                        .format( (TMergeSqlStatement) sql );
446                }
447                else if ( sql instanceof TIfStmt )
448                {
449                        FormatterFactory.createPlsqlIfStmtFormatter( option )
450                                        .format( (TIfStmt) sql );
451                }
452                else
453                {
454                        FormatterFactory.createCommonStatement( option ).format( sql );
455                }
456        }
457
458        private static AbstractStmtFormatter<TCommonBlock> createPlsqlBlockStmtFormatter(
459                        GFmtOpt opt )
460        {
461                return createFormatter( opt,
462                                PlsqlBlockStmtFormatter.class,
463                                new IFormatterBuilderCreator<PlsqlBlockStmtFormatter>( ) {
464
465                                        public AbstractStmtFormatterBuilder<PlsqlBlockStmtFormatter> create( )
466                                        {
467                                                return new PlsqlBlockStmtFormatterBuilder( );
468                                        }
469                                } );
470        }
471
472        private static MergeStmtFormatter createMergeSqlStatement( GFmtOpt opt )
473        {
474                return createFormatter( opt,
475                                MergeStmtFormatter.class,
476                                new IFormatterBuilderCreator<MergeStmtFormatter>( ) {
477
478                                        public AbstractStmtFormatterBuilder<MergeStmtFormatter> create( )
479                                        {
480                                                return new MergeStmtFormatterBuilder( );
481                                        }
482                                } );
483        }
484
485        private static CommonStmtFormatter createCommonStatement( GFmtOpt opt )
486        {
487                return createFormatter( opt,
488                                CommonStmtFormatter.class,
489                                new IFormatterBuilderCreator<CommonStmtFormatter>( ) {
490
491                                        public AbstractStmtFormatterBuilder<CommonStmtFormatter> create( )
492                                        {
493                                                return new CommonStmtFormatterBuilder( );
494                                        }
495                                } );
496        }
497
498        public static boolean isNotNeedFormat( TCustomSqlStatement sql )
499        {
500                if ( sql == null )
501                {
502                        // the null statement needn't formatting.
503                        return true;
504                }
505                if ( sql.getStartToken( ) != null )
506                {
507                        TSourceToken t = sql.getStartToken( );
508                        return isNotNeedFormat( t );
509                }
510                return false;
511        }
512
513        public static boolean isNotNeedFormat( TSourceToken t )
514        {
515                if ( t == null )
516                {
517                        return false;
518                }
519                TSourceTokenList bts = t.getTokensBefore( );
520                if ( bts.size( ) > 0 )
521                {
522                        for ( int i = 0; i < bts.size( ); i++ )
523                        {
524                                if ( SourceTokenOperator.createNoFormatFlagToken( )
525                                                .equals( bts.get( i ) ) )
526                                {
527                                        return true;
528                                }
529                        }
530                }
531                return false;
532        }
533
534        public static void processBlockStmt( GFmtOpt opt, TMssqlBlock stmt,
535                        TSourceToken ifToken )
536        {
537                TSourceToken startToken = stmt.getStartToken( );
538                TSourceToken endToken = stmt.getEndToken( );
539                if ( startToken == null || endToken == null )
540                {
541                        return;
542                }
543                int curBeginIndent = SourceTokenOperator.curColumnNumberVT( ifToken );
544                if ( opt.beStyleBlockLeftBEOnNewline )
545                {
546                        curBeginIndent += opt.beStyleBlockLeftBEIndentSize;
547                        // process the begin token
548                        SourceTokenOperator.addBefore( opt,
549                                        startToken,
550                                        SourceTokenOperator.createReturnSourceToken( ) );
551                        SourceTokenOperator.addBefore( opt,
552                                        startToken,
553                                        SourceTokenOperator.createWhitespaceSourceToken( curBeginIndent ) );
554                }
555                // process the end token
556                int curEndIndent = SourceTokenOperator.curColumnNumberVT( ifToken )
557                                + ( opt.beStyleBlockLeftBEOnNewline ? opt.beStyleBlockLeftBEIndentSize
558                                                : opt.beStyleBlockRightBEIndentSize );
559                SourceTokenOperator.addBefore( opt,
560                                endToken,
561                                SourceTokenOperator.createReturnSourceToken( ) );
562                SourceTokenOperator.addBefore( opt,
563                                endToken,
564                                SourceTokenOperator.createWhitespaceSourceToken( curEndIndent ) );
565
566                TStatementList list = stmt.getBodyStatements( );
567
568                // first, process the indent for the first statement
569                if ( list != null && list.size( ) > 0 )
570                {
571                        int curBlockIndent = curEndIndent + opt.beStyleBlockIndentSize;
572                        TCustomSqlStatement bstmt = list.get( 0 );
573                        TSourceToken bstartToken = bstmt.getStartToken( );
574                        if ( bstartToken != null )
575                        {
576                                SourceTokenOperator.addBefore( opt,
577                                                bstartToken,
578                                                SourceTokenOperator.createReturnSourceToken( ) );
579                                SourceTokenOperator.addBefore( opt,
580                                                bstartToken,
581                                                SourceTokenOperator.createWhitespaceSourceToken( curBlockIndent ) );
582                        }
583                }
584                // second, process all the empty lines between the statements
585                AllStmtsFormatter.processEmptyLine( list, opt, true );
586
587                // third, format the statements in the begin-end block
588                if ( list != null && list.size( ) > 0 )
589                {
590                        // int curBlockIndent = curEndIndent + opt.beStyleBlockIndentSize;
591                        for ( int i = 0; i < list.size( ); i++ )
592                        {
593                                TCustomSqlStatement bstmt = list.get( i );
594                                // TSourceToken bstartToken = bstmt.getStartToken();
595                                // if (bstartToken != null) {
596                                // SourceTokenOperator.addBefore(opt, bstartToken,
597                                // SourceTokenOperator.createReturnSourceToken());
598                                // if (i != 0 && opt.insertBlankLineInBatchSqls) {
599                                // TCustomSqlStatement preBstmt = list.get(i - 1);
600                                // TSourceToken preBEndToken = preBstmt.getEndToken();
601                                // if (preBEndToken != null) {
602                                // SourceTokenOperator.addAfter(opt, preBstmt.getEndToken(),
603                                // SourceTokenOperator.createReturnSourceToken());
604                                // }
605                                // }
606                                // SourceTokenOperator.addBefore(opt, bstartToken,
607                                // SourceTokenOperator.createWhitespaceSourceToken(curBlockIndent));
608                                //
609                                // }
610                                FormatterFactory.processStatement( opt, bstmt );
611
612                        }
613                }
614
615        }
616
617        public static String pp( TGSqlParser parser, GFmtOpt option )
618        {
619                if (option.removeComment) {
620                        parser = SqlFormatter.preHandleRemoveComment(parser);
621                }
622                OutputStream o = new ByteArrayOutputStream( );
623                IPrinter printer = PrinterFactory.createTextPrinter( o );
624
625                FormatterFactory.createAllStmtsFormatter( option )
626                                .beforeFormat( parser.sqlstatements );
627
628                for ( int i = 0; i < parser.sqlstatements.size( ); i++ )
629                {
630                        TCustomSqlStatement sql = parser.sqlstatements.get( i );
631                        processStatement( option, sql );
632                }
633                if ( parser.sqlstatements != null && parser.sqlstatements.size( ) > 0 )
634                {
635                        FormatterFactory.createAllStmtsFormatter( option )
636                                        .doFormat( parser.sqlstatements );
637                        FormatterFactory.createAllStmtsFormatter( option )
638                                        .afterFormat( parser.sqlstatements );
639
640                        if ( outputConfig == null )
641                        {
642                                outputConfig = OutputConfigFactory.getOutputConfig( option,
643                                                parser.getDbVendor( ) );
644                        }
645
646                        printer.setOutputConfig( outputConfig );
647                        printer.print( parser.sqlstatements.get( 0 ).getStartToken( ).container );
648                }
649
650                clearAllObject( option.sessionId );
651                return o.toString( );
652
653        }
654
655        /**
656         * Fault-tolerant formatter entry point (pp2). Unlike {@link #pp(TGSqlParser, GFmtOpt)},
657         * this does <b>not</b> require {@code parser.parse()} to have returned 0: it
658         * re-tokenizes {@code parser.sqltext} internally, splits the script into
659         * statement regions, formats each region independently, and recovers
660         * gracefully from malformed input. It never throws for non-null inputs and
661         * preserves every solid input token.
662         *
663         * <p>This is the single additive pp2 bridge (plan ยง4.1/S17). It does not
664         * change the behavior of {@link #pp(TGSqlParser, GFmtOpt)} or any other
665         * existing method. The heavy lifting lives in
666         * {@code gudusoft.gsqlparser.pp2.engine.Pp2Engine}.
667         *
668         * @param parser carries the SQL text ({@code parser.sqltext}) and dialect
669         *               ({@code parser.getDbVendor()}); need not be parsed first
670         * @param opts   pp2 formatting options; must not be null
671         * @return a structured {@link Pp2FormatResult} with per-region renderer
672         *         choice, status, and diagnostics; never null
673         * @throws NullPointerException if {@code parser} or {@code opts} is null
674         */
675        public static Pp2FormatResult pp2( TGSqlParser parser, Pp2FormatOptions opts )
676        {
677                if ( parser == null ) throw new NullPointerException( "parser" );
678                if ( opts == null ) throw new NullPointerException( "opts" );
679                String sql = parser.sqltext == null ? "" : parser.sqltext;
680                return new Pp2Engine( ).format( sql, parser.getDbVendor( ), opts );
681        }
682
683        /**
684         * Convenience overload mirroring the {@link #pp(TGSqlParser, GFmtOpt)}
685         * signature: returns the formatted text directly. The caller's
686         * {@link GFmtOpt} is copied into a {@link Pp2FormatOptions} via
687         * {@link Pp2FormatOptions#from(GFmtOpt)} so casing/comma/indent options
688         * carry over (giving byte-parity with {@code pp()} on parseable input).
689         *
690         * @param parser carries the SQL text and dialect; need not be parsed first
691         * @param opt    existing formatter options; must not be null
692         * @return the formatted SQL text; never null
693         * @throws NullPointerException if {@code parser} or {@code opt} is null
694         */
695        public static String pp2( TGSqlParser parser, GFmtOpt opt )
696        {
697                if ( parser == null ) throw new NullPointerException( "parser" );
698                if ( opt == null ) throw new NullPointerException( "opt" );
699                return pp2( parser, Pp2FormatOptions.from( opt ) ).getText( );
700        }
701
702        public static OutputConfig getOutputConfig( )
703        {
704                return outputConfig;
705        }
706
707        public static void setOutputConfig( OutputConfig outputConfig )
708        {
709                FormatterFactory.outputConfig = outputConfig;
710        }
711
712        public static AllStmtsFormatter createAllStmtsFormatter( GFmtOpt option )
713        {
714                return AllStmtsFormatterBuilder.create( option );
715        }
716
717        public static void clearAllObject( String sessionId )
718        {
719                FormatterFactory.clear( sessionId );
720                ProcessorFactory.clear( sessionId );
721                MediatorFactory.clear( sessionId );
722        }
723
724        public static void clear( String sessionId )
725        {
726                synchronized ( object )
727                {
728                        List<String> removedKeys = new ArrayList<String>( );
729                        for ( String key : formatter.keySet( ) )
730                        {
731                                if ( key.startsWith( sessionId ) )
732                                {
733                                        removedKeys.add( key );
734                                }
735                        }
736                        for ( String key : removedKeys )
737                        {
738                                formatter.remove( key );
739                        }
740                }
741        }
742}