001    package railo.transformer.cfml.expression;
002    
003    
004    import java.util.ArrayList;
005    import java.util.Iterator;
006    
007    import railo.runtime.exp.CasterException;
008    import railo.runtime.exp.PageExceptionImpl;
009    import railo.runtime.exp.TemplateException;
010    import railo.runtime.op.Caster;
011    import railo.runtime.type.Scope;
012    import railo.runtime.type.scope.ScopeSupport;
013    import railo.transformer.bytecode.BytecodeException;
014    import railo.transformer.bytecode.cast.CastDouble;
015    import railo.transformer.bytecode.cast.CastString;
016    import railo.transformer.bytecode.expression.ExprDouble;
017    import railo.transformer.bytecode.expression.ExprString;
018    import railo.transformer.bytecode.expression.Expression;
019    import railo.transformer.bytecode.expression.ExpressionInvoker;
020    import railo.transformer.bytecode.expression.Invoker;
021    import railo.transformer.bytecode.expression.var.Argument;
022    import railo.transformer.bytecode.expression.var.Assign;
023    import railo.transformer.bytecode.expression.var.BIF;
024    import railo.transformer.bytecode.expression.var.DataMember;
025    import railo.transformer.bytecode.expression.var.DynAssign;
026    import railo.transformer.bytecode.expression.var.FunctionMember;
027    import railo.transformer.bytecode.expression.var.Member;
028    import railo.transformer.bytecode.expression.var.NamedArgument;
029    import railo.transformer.bytecode.expression.var.UDF;
030    import railo.transformer.bytecode.expression.var.Variable;
031    import railo.transformer.bytecode.literal.LitBoolean;
032    import railo.transformer.bytecode.literal.LitDouble;
033    import railo.transformer.bytecode.literal.LitString;
034    import railo.transformer.bytecode.op.OPDecision;
035    import railo.transformer.bytecode.op.OpBool;
036    import railo.transformer.bytecode.op.OpContional;
037    import railo.transformer.bytecode.op.OpDouble;
038    import railo.transformer.bytecode.op.OpNegate;
039    import railo.transformer.bytecode.op.OpNegateNumber;
040    import railo.transformer.bytecode.op.OpString;
041    import railo.transformer.bytecode.op.OpVariable;
042    import railo.transformer.cfml.ExprTransformer;
043    import railo.transformer.cfml.evaluator.EvaluatorPool;
044    import railo.transformer.cfml.script.DocComment;
045    import railo.transformer.cfml.script.DocCommentTransformer;
046    import railo.transformer.cfml.tag.CFMLTransformer;
047    import railo.transformer.library.function.FunctionLib;
048    import railo.transformer.library.function.FunctionLibFunction;
049    import railo.transformer.library.function.FunctionLibFunctionArg;
050    import railo.transformer.library.tag.TagLibTag;
051    import railo.transformer.library.tag.TagLibTagScript;
052    import railo.transformer.util.CFMLString;
053    
054    /**
055     * 
056     * 
057            Der CFMLExprTransfomer implementiert das Interface ExprTransfomer, 
058            er bildet die Parser Grammatik ab, die unten definiert ist. 
059            Er erh¦lt als Eingabe CFML Code, als String oder CFMLString, 
060            der einen CFML Expression erh¦lt und liefert ein CFXD Element zurck, 
061            das diesen Ausdruck abbildet.
062            Mithilfe der FunctionLibメs, kann er Funktionsaufrufe, 
063            die Teil eines Ausdruck sein k￶nnen, erkennen und validieren. 
064            Dies geschieht innerhalb der Methode function.
065            Falls ein Funktionsaufruf, einer Funktion innerhalb einer FunctionLib entspricht, 
066            werden diese gegeneinander verglichen und der Aufruf wird als Build-In-Funktion bernommen, 
067            andernfalls wird der Funktionsaufruf als User-Defined-Funktion interpretiert.
068            Die Klasse Cast, Operator und ElementFactory (siehe 3.2) helfen ihm beim erstellen des Ausgabedokument CFXD.
069    
070     * <pre>
071     * Parser Grammatik EBNF (Extended Backus-Naur Form) 
072    
073            transform      = spaces impOp;
074            impOp          = eqvOp {"imp" spaces eqvOp};
075            eqvOp          = xorOp {"eqv" spaces xorOp};
076            xorOp          = orOp {"xor" spaces  orOp};
077            orOp           = andOp {("or" | "||") spaces andOp}; 
078                            (* "||" Existiert in CFMX nicht *)
079            andOp          = notOp {("and" | "&&") spaces notOp}; 
080                            (* "&&" Existiert in CFMX nicht *) 
081            notOp          = [("not"|"!") spaces] decsionOp; 
082                            (* "!" Existiert in CFMX nicht *)
083            decsionOp      = concatOp {("neq"|"eq"|"gte"|"gt"|"lte"|"lt"|"ct"|
084                             "contains"|"nct"|"does not contain") spaces concatOp}; 
085                            (* "ct"=conatains und "nct"=does not contain; Existiert in CFMX nicht *)
086            concatOp       = plusMinusOp {"&" spaces plusMinusOp};
087            plusMinusOp    = modOp {("-"|"+") spaces modOp};
088            modOp          = divMultiOp {("mod" | "%") spaces divMultiOp}; 
089                            (* modulus operator , "%" Existiert in CFMX nicht *)
090            divMultiOp     = expoOp {("*"|"/") spaces expoOp};
091            expoOp         = clip {("exp"|"^") spaces clip}; 
092                            (*exponent operator, " exp " Existiert in CFMX nicht *)
093            clip           = ("(" spaces impOp ")" spaces) | checker;
094            checker        = string | number | dynamic | sharp;
095            string         = ("'" {"##"|"''"|"#" impOp "#"| ?-"#"-"'" } "'") | 
096                             (""" {"##"|""""|"#" impOp "#"| ?-"#"-""" } """);
097            number         = ["+"|"-"] digit {digit} {"." digit {digit}};
098            digit          = "0"|..|"9";
099            dynamic        = "true" | "false" | "yes" | "no" | startElement  
100                             {("." identifier | "[" structElement "]")[function] };
101            startElement   = identifier "(" functionArg ")" | scope | identifier;
102            scope          = "variable" | "cgi" | "url" | "form" | "session" | "application" | 
103                             "arguments" | "cookie" | "client ";
104            identifier     = (letter | "_") {letter | "_"|digit};
105            structElement  = "[" impOp "]";
106            functionArg    = [impOp{"," impOp}];
107            sharp          = "#" checker "#";
108            spaces         = {space};
109            space          = "\s"|"\t"|"\f"|"\t"|"\n";
110            letter         = "a"|..|"z"|"A"|..|"Z";
111    
112    {"x"}= 0 bis n mal "x"
113    ["x"]= 0 bis 1 mal "x"
114    ("x" | "y")"z" = "xz" oder "yz"
115    
116    </pre>
117     *
118     */
119    public class CFMLExprTransformer implements ExprTransformer {
120    
121            private static final short STATIC=0;
122            private static final short DYNAMIC=1;
123            private static FunctionLibFunction JSON_ARRAY = null;
124            private static FunctionLibFunction JSON_STRUCT = null;
125    
126            public static final short CTX_OTHER = TagLibTagScript.CTX_OTHER;
127            public static final short CTX_NONE = TagLibTagScript.CTX_NONE;
128            public static final short CTX_IF = TagLibTagScript.CTX_IF;
129            public static final short CTX_ELSE_IF = TagLibTagScript.CTX_ELSE_IF;
130            public static final short CTX_ELSE = TagLibTagScript.CTX_ELSE;
131            public static final short CTX_FOR = TagLibTagScript.CTX_FOR;
132            public static final short CTX_WHILE = TagLibTagScript.CTX_WHILE;
133            public static final short CTX_DO_WHILE = TagLibTagScript.CTX_DO_WHILE;
134            public static final short CTX_CFC = TagLibTagScript.CTX_CFC;
135            public static final short CTX_INTERFACE = TagLibTagScript.CTX_INTERFACE;
136            public static final short CTX_FUNCTION =TagLibTagScript.CTX_FUNCTION;
137            public static final short CTX_BLOCK = TagLibTagScript.CTX_BLOCK;
138            public static final short CTX_FINALLY = TagLibTagScript.CTX_FINALLY;
139            public static final short CTX_SWITCH = TagLibTagScript.CTX_SWITCH;
140            public static final short CTX_TRY = TagLibTagScript.CTX_TRY;
141            public static final short CTX_CATCH = TagLibTagScript.CTX_CATCH;
142            public static final short CTX_TRANSACTION = TagLibTagScript.CTX_TRANSACTION;
143            public static final short CTX_THREAD = TagLibTagScript.CTX_THREAD;
144            public static final short CTX_SAVECONTENT = TagLibTagScript.CTX_SAVECONTENT;
145            public static final short CTX_LOCK = TagLibTagScript.CTX_LOCK;
146            public static final short CTX_LOOP = TagLibTagScript.CTX_LOOP;
147            public static final short CTX_QUERY = TagLibTagScript.CTX_QUERY;
148            public static final short CTX_ZIP = TagLibTagScript.CTX_ZIP;
149            
150            
151            private DocCommentTransformer docCommentTransformer= new DocCommentTransformer();
152            
153            
154            /*private short mode=0;
155            protected CFMLString cfml;
156            protected FunctionLib[] fld;
157            private boolean ignoreScopes=false;
158            private boolean allowLowerThan;*/
159            
160            public class Data {
161                    
162                    private short mode=0;
163                    public CFMLString cfml;
164                    public FunctionLib[] fld;
165                    private boolean ignoreScopes=false;
166                    private boolean allowLowerThan;
167                    public boolean insideFunction;
168                    public String tagName;
169                    public boolean isCFC;
170                    public boolean isInterface;
171                    public EvaluatorPool ep;
172                    public short context=CTX_NONE; 
173                    public TagLibTag[] scriptTags;
174                    public DocComment docComment;
175                    
176                    public Data(EvaluatorPool ep, CFMLString cfml, FunctionLib[] fld,boolean allowLowerThan) {
177                            this.ep=ep;
178                            this.cfml=cfml;
179                            this.fld=fld;
180                            this.allowLowerThan=allowLowerThan;
181                    }
182            }
183            
184            /**
185             * Wird aufgerufen um aus dem bergebenen CFMLString einen Ausdruck auszulesen 
186             * und diesen in ein CFXD Element zu bersetzten.
187             * <br />
188             * Beispiel eines bergebenen String:<br />
189             * <code>session.firstName</code> oder <code>trim(left('test'&var1,3))</code>
190             * <br />
191             * EBNF:<br />
192             * <code>spaces impOp;</code>
193             * 
194             * @param fld Array von Function Libraries, 
195             * Mithilfe dieser Function Libraries kann der Transfomer buil-in Funktionen innerhalb des CFML Codes erkennen 
196             * und validieren.
197             * @param doc XML Document des aktuellen zu erstellenden CFXD
198             * @param cfml Text der transfomiert werden soll.
199             * @return Element CFXD Element
200             * @throws TemplateException
201             */
202            public Expression transform(EvaluatorPool ep,FunctionLib[] fld, CFMLString cfml) throws TemplateException {
203                    
204                    // Init Parameter
205                    Data data = init(ep,fld, cfml,false);
206    
207                    // parse the houle Page String
208            comments(data);
209                    //Expression expr = assignOp();
210    
211                    // return the Root Element of the Document      
212                    return assignOp(data);
213            }
214            
215            /**
216             * @see railo.transformer.data.cfml.ExprTransformer#transformAsString(railo.transformer.library.function.FunctionLib[], org.w3c.dom.Document, railo.transformer.util.CFMLString)
217             */
218            public Expression transformAsString(EvaluatorPool ep,FunctionLib[] fld, CFMLString cfml, boolean allowLowerThan) throws TemplateException {
219                    
220                    return transformAsString(init(ep,fld, cfml,allowLowerThan),new String[]{" ", ">", "/>"});
221            }
222            
223            protected Expression transformAsString(Data data,String[] breakConditions) throws TemplateException {
224                    Expression el=null;
225                    
226                    // parse the houle Page String
227            comments(data);         
228                                    
229                    // String
230                            if((el=string(data))!=null) {
231                                    data.mode=STATIC;
232                                    return el;
233                            } 
234                    // Sharp
235                            if((el=sharp(data))!=null) {
236                                    data.mode=DYNAMIC;
237                                    return el;
238                            }  
239                    // Simple
240                            return simple(data,breakConditions);
241            }
242            
243            
244    
245            /**
246             * Initialmethode, wird aufgerufen um den internen Zustand des Objektes zu setzten.
247             * @param fld Function Libraries zum validieren der Funktionen
248             * @param doc XML Document des aktuellen CFXD
249             * @param cfml CFML Code der transfomiert werden soll.
250             */
251            protected Data init(EvaluatorPool ep,FunctionLib[] fld, CFMLString cfml, boolean allowLowerThan) {
252                    Data data = new Data(ep,cfml,fld,allowLowerThan);
253                    if(JSON_ARRAY==null)JSON_ARRAY=getFLF(data,"_jsonArray");
254                    if(JSON_STRUCT==null)JSON_STRUCT=getFLF(data,"_jsonStruct");
255                    return data;
256                    //this.allowLowerThan=allowLowerThan;
257                    //this.fld = fld;
258                    //this.cfml = cfml;
259            }
260            
261            /**
262             * Startpunkt zum transfomieren einer Expression, ohne dass das Objekt neu initialisiert wird, 
263             * dient vererbten Objekten als Einstiegspunkt.
264             * @return Element
265             * @throws TemplateException
266             */
267            protected Expression expression(Data data) throws TemplateException {
268                    return assignOp(data);
269            }
270    
271            /**
272            * Liest einen gelableten  Funktionsparamter ein
273            * <br />
274            * EBNF:<br />
275            * <code>assignOp [":" spaces assignOp];</code>
276             * @param type 
277            * @return CFXD Element
278            * @throws TemplateException 
279            */
280            protected Argument functionArgument(Data data) throws TemplateException {
281                    return functionArgument(data,null);
282            }
283            
284            protected Argument functionArgument(Data data,String type) throws TemplateException {
285                    Expression expr = assignOp(data);
286                    try{
287                            if (data.cfml.forwardIfCurrent(":")) {
288                                    comments(data);
289                        return new NamedArgument(expr,assignOp(data),type);
290                            }
291                            else if(expr instanceof DynAssign){
292                                    DynAssign da=(DynAssign) expr;
293                                    return new NamedArgument(da.getName(),da.getValue(),type);
294                            }
295                            else if(expr instanceof Assign && !(expr instanceof OpVariable)){
296                                    Assign a=(Assign) expr;
297                                    return new NamedArgument(a.getVariable(),a.getValue(),type);
298                            }
299                    }
300                    catch(BytecodeException be) {
301                            throw new TemplateException(data.cfml,be.getMessage());
302                    }
303                    return new Argument(expr,type);
304            }
305    
306            /**
307            * Transfomiert Zuweisungs Operation.
308            * <br />
309            * EBNF:<br />
310            * <code>eqvOp ["=" spaces assignOp];</code>
311            * @return CFXD Element
312            * @throws TemplateException 
313            */
314            protected Expression assignOp(Data data) throws TemplateException {
315            
316                    Expression expr = conditionalOp(data);
317            if (data.cfml.forwardIfCurrent('=')) {
318                    
319                comments(data);
320                if(data.mode==STATIC) expr=new DynAssign(expr,assignOp(data));
321                            else {
322                                    if(expr instanceof Variable)
323                                            expr=new Assign((Variable)expr,assignOp(data));
324                                    else
325                                            throw new TemplateException(data.cfml,"invalid assignment left-hand side ("+expr.getClass().getName()+")");
326                            }
327                    }
328                    return expr;
329            }
330            
331            protected Expression conditionalOp(Data data) throws TemplateException {
332            
333                    Expression expr = impOp(data);
334            if (data.cfml.forwardIfCurrent('?')) {
335                    comments(data);
336                    Expression left = assignOp(data);
337                    comments(data);
338                    if(!data.cfml.forwardIfCurrent(':'))throw new TemplateException("invalid conditional operator");
339                    comments(data); 
340                    Expression right = assignOp(data);
341                    
342                expr=OpContional.toExpr(expr, left, right);
343                    }
344                    return expr;
345            }
346    
347            /**
348            * Transfomiert eine Implication (imp) Operation.
349            * <br />
350            * EBNF:<br />
351            * <code>eqvOp {"imp" spaces eqvOp};</code>
352            * @return CFXD Element
353            * @throws TemplateException 
354            */
355            protected Expression impOp(Data data) throws TemplateException {
356                    Expression expr = eqvOp(data);
357                    while(data.cfml.forwardIfCurrentAndNoWordAfter("imp")) { 
358                            comments(data);
359                expr=OpBool.toExprBoolean(expr, eqvOp(data), OpBool.IMP);
360                    }
361                    return expr;
362            }
363    
364            /**
365            * Transfomiert eine  Equivalence (eqv) Operation.
366            * <br />
367            * EBNF:<br />
368            * <code>xorOp {"eqv" spaces xorOp};</code>
369            * @return CFXD Element
370            * @throws TemplateException 
371            */
372            protected Expression eqvOp(Data data) throws TemplateException {
373                    Expression expr = xorOp(data);
374                    while(data.cfml.forwardIfCurrentAndNoWordAfter("eqv")) {
375                            comments(data);
376                expr=OpBool.toExprBoolean(expr, xorOp(data), OpBool.EQV);
377                    }
378                    return expr;
379            }
380    
381            /**
382            * Transfomiert eine  Xor (xor) Operation.
383            * <br />
384            * EBNF:<br />
385            * <code>orOp {"xor" spaces  orOp};</code>
386            * @return CFXD Element
387            * @throws TemplateException 
388            */
389            protected Expression xorOp(Data data) throws TemplateException {
390                    Expression expr = orOp(data);
391                    while(data.cfml.forwardIfCurrentAndNoWordAfter("xor")) {
392                            comments(data);
393                expr=OpBool.toExprBoolean(expr, orOp(data), OpBool.XOR);
394                    }
395                    return expr;
396            }
397    
398            /**
399            * Transfomiert eine  Or (or) Operation. Im Gegensatz zu CFMX ,
400            * werden "||" Zeichen auch als Or Operatoren anerkannt.
401            * <br />
402            * EBNF:<br />
403            * <code>andOp {("or" | "||") spaces andOp}; (* "||" Existiert in CFMX nicht *)</code>
404            * @return CFXD Element
405            * @throws TemplateException 
406            */
407            protected Expression orOp(Data data) throws TemplateException {
408                    Expression expr = andOp(data);
409                    
410                    while(data.cfml.forwardIfCurrent("||") || data.cfml.forwardIfCurrentAndNoWordAfter("or")) {
411                            comments(data);
412                expr=OpBool.toExprBoolean(expr, andOp(data), OpBool.OR);
413                    }
414                    return expr;
415            }
416    
417            /**
418            * Transfomiert eine  And (and) Operation. Im Gegensatz zu CFMX ,
419            * werden "&&" Zeichen auch als And Operatoren anerkannt.
420            * <br />
421            * EBNF:<br />
422            * <code>notOp {("and" | "&&") spaces notOp}; (* "&&" Existiert in CFMX nicht *)</code>
423            * @return CFXD Element
424            * @throws TemplateException 
425            */
426            protected Expression andOp(Data data) throws TemplateException {
427                    Expression expr = notOp(data);
428                    
429                    while(data.cfml.forwardIfCurrent("&&") || data.cfml.forwardIfCurrentAndNoWordAfter("and")) {
430                            comments(data);
431                    expr=OpBool.toExprBoolean(expr, notOp(data), OpBool.AND);
432                    }
433                    return expr;
434            }
435    
436            /**
437            * Transfomiert eine  Not (not) Operation. Im Gegensatz zu CFMX ,
438            * wird das "!" Zeichen auch als Not Operator anerkannt.
439            * <br />
440            * EBNF:<br />
441            * <code>[("not"|"!") spaces] decsionOp; (* "!" Existiert in CFMX nicht *)</code>
442            * @return CFXD Element
443            * @throws TemplateException 
444            */
445            protected Expression notOp(Data data) throws TemplateException {
446                    // And Operation
447                    int line=data.cfml.getLine();
448                    if (data.cfml.isCurrent('!') && !data.cfml.isCurrent("!=")) {
449                            data.cfml.next();
450                            comments(data);
451                            return OpNegate.toExprBoolean(notOp(data),line);
452                    }
453                    else if (data.cfml.forwardIfCurrentAndNoWordAfter("not")) {
454                            comments(data);
455                            return OpNegate.toExprBoolean(notOp(data),line);
456                    }
457                    return decsionOp(data);
458            }
459    
460            /**
461            * <font f>Transfomiert eine Vergleichs Operation.
462            * <br />
463            * EBNF:<br />
464            * <code>concatOp {("neq"|"eq"|"gte"|"gt"|"lte"|"lt"|"ct"|
465                             "contains"|"nct"|"does not contain") spaces concatOp}; 
466                            (* "ct"=conatains und "nct"=does not contain; Existiert in CFMX nicht *)</code>
467            * @return CFXD Element
468            * @throws TemplateException 
469            */
470            protected Expression decsionOp(Data data) throws TemplateException {
471    
472                    Expression expr = concatOp(data);
473                    boolean hasChanged=false;
474                    // ct, contains
475                    do {
476                            hasChanged=false;
477                            if(data.cfml.isCurrent('c')) {
478                                            if (data.cfml.forwardIfCurrent("ct",false,true)) {expr = decisionOpCreate(data,OPDecision.CT,expr);hasChanged=true;} 
479                                            else if (data.cfml.forwardIfCurrent("contains",false,true)){ expr = decisionOpCreate(data,OPDecision.CT,expr);hasChanged=true;}
480                            }
481                            // does not contain
482                            else if (data.cfml.forwardIfCurrent("does","not","contain",false,true)){ expr = decisionOpCreate(data,OPDecision.NCT,expr); hasChanged=true;}
483    
484                            // equal, eq
485                            else if (data.cfml.isCurrent("eq") && !data.cfml.isCurrent("eqv")) {
486                                    int plus=2;
487                                    data.cfml.setPos(data.cfml.getPos()+2);
488                                    if(data.cfml.forwardIfCurrent("ual"))plus=5;
489                                    
490                                    if(data.cfml.isCurrentVariableCharacter()) {
491                                            data.cfml.setPos(data.cfml.getPos()-plus);
492                                    }
493                                    else {
494                                            expr = decisionOpCreate(data,OPDecision.EQ,expr);
495                                            hasChanged=true;
496                                    }
497                                    
498                            }
499                            // ==
500                            else if (data.cfml.forwardIfCurrent("==")) {
501                                    if(data.cfml.forwardIfCurrent('='))             expr = decisionOpCreate(data,OPDecision.EEQ,expr);
502                                    else expr = decisionOpCreate(data,OPDecision.EQ,expr);
503                                    hasChanged=true;
504                            }
505                            // !=
506                            else if (data.cfml.forwardIfCurrent("!=")) {
507                                    if(data.cfml.forwardIfCurrent('='))             expr = decisionOpCreate(data,OPDecision.NEEQ,expr);
508                                    else expr = decisionOpCreate(data,OPDecision.NEQ,expr); 
509                                    hasChanged=true;
510                            }
511                            // <=/</<>
512                            else if (data.cfml.isCurrent('<')) {
513                                    hasChanged=true;
514                                    if(data.cfml.isNext('='))       {
515                                            data.cfml.next();data.cfml.next();
516                                            expr = decisionOpCreate(data,OPDecision.LTE,expr);
517                                    }
518                                    else if(data.cfml.isNext('>')) {
519                                            data.cfml.next();data.cfml.next();
520                                            expr = decisionOpCreate(data,OPDecision.NEQ,expr);
521                                    }
522                                    else if(data.cfml.isNext('/')) {
523                                            hasChanged=false;
524                                    }
525                                    else    {
526                                            data.cfml.next();
527                                            expr = decisionOpCreate(data,OPDecision.LT,expr); 
528                                    }
529                            }
530                            // >=/>
531                            else if (data.allowLowerThan && data.cfml.forwardIfCurrent('>')) {
532                                    if(data.cfml.forwardIfCurrent('='))     expr = decisionOpCreate(data,OPDecision.GTE,expr);
533                                    else                                                    expr = decisionOpCreate(data,OPDecision.GT,expr); 
534                                    hasChanged=true;
535                            }
536                            
537                            // gt, gte, greater than or equal to, greater than
538                            else if (data.cfml.isCurrent('g')) {
539                                    if (data.cfml.forwardIfCurrent("gt")) {
540                                            if(data.cfml.forwardIfCurrentAndNoWordAfter("e")) {
541                                                    if(data.cfml.isCurrentVariableCharacter()) {
542                                                            data.cfml.setPos(data.cfml.getPos()-3);
543                                                    }
544                                                    else {
545                                                            expr = decisionOpCreate(data,OPDecision.GTE,expr);
546                                                            hasChanged=true;
547                                                    }
548                                            }
549                                            else {
550                                                    if(data.cfml.isCurrentVariableCharacter()) {
551                                                            data.cfml.setPos(data.cfml.getPos()-2);
552                                                    }
553                                                    else {
554                                                            expr = decisionOpCreate(data,OPDecision.GT,expr);
555                                                            hasChanged=true;
556                                                    }
557                                            }
558                                    } 
559                                    else if (data.cfml.forwardIfCurrent("greater", "than",false,true)) {
560                                            if(data.cfml.forwardIfCurrent("or","equal", "to",true,true)) expr = decisionOpCreate(data,OPDecision.GTE,expr);
561                                            else expr = decisionOpCreate(data,OPDecision.GT,expr);
562                                            hasChanged=true;
563                                    }       
564                                    else if (data.cfml.forwardIfCurrent("ge",false,true)) {
565                                            expr = decisionOpCreate(data,OPDecision.GTE,expr);
566                                            hasChanged=true;
567                                    }                               
568                            }
569                            
570                            // is, is not
571                            else if (data.cfml.forwardIfCurrent("is",false,true)) {
572                                    if(data.cfml.forwardIfCurrent("not",true,true)) expr = decisionOpCreate(data,OPDecision.NEQ,expr);
573                                    else expr = decisionOpCreate(data,OPDecision.EQ,expr);
574                                    hasChanged=true;
575                            }
576                            
577                            // lt, lte, less than, less than or equal to
578                            else if (data.cfml.isCurrent('l')) {
579                                    if (data.cfml.forwardIfCurrent("lt")) {
580                                            if(data.cfml.forwardIfCurrentAndNoWordAfter("e")) {
581                                                    if(data.cfml.isCurrentVariableCharacter()) {
582                                                            data.cfml.setPos(data.cfml.getPos()-3);
583                                                    }
584                                                    else {
585                                                            expr = decisionOpCreate(data,OPDecision.LTE,expr);
586                                                            hasChanged=true;
587                                                    }
588                                            }
589                                            else {
590                                                    if(data.cfml.isCurrentVariableCharacter()) {
591                                                            data.cfml.setPos(data.cfml.getPos()-2);
592                                                    }
593                                                    else {
594                                                            expr = decisionOpCreate(data,OPDecision.LT,expr);
595                                                            hasChanged=true;
596                                                    }
597                                            }
598                                    } 
599                                    else if (data.cfml.forwardIfCurrent("less","than",false,true)) {
600                                            if(data.cfml.forwardIfCurrent("or", "equal", "to",true,true)) expr = decisionOpCreate(data,OPDecision.LTE,expr);
601                                            else expr = decisionOpCreate(data,OPDecision.LT,expr);
602                                            hasChanged=true;
603                                    }       
604                                    else if (data.cfml.forwardIfCurrent("le",false,true)) {
605                                            expr = decisionOpCreate(data,OPDecision.LTE,expr);
606                                            hasChanged=true;
607                                    }                               
608                            }
609                            
610                            // neq, not equal, nct
611                            else if (data.cfml.isCurrent('n')) {
612                                    // Not Equal
613                                            if (data.cfml.forwardIfCurrent("neq",false,true)){ expr = decisionOpCreate(data,OPDecision.NEQ,expr); hasChanged=true;}
614                                    // Not Equal (Alias)
615                                            else if (data.cfml.forwardIfCurrent("not","equal",false,true)){ expr = decisionOpCreate(data,OPDecision.NEQ,expr);hasChanged=true; }
616                                    // nct
617                                            else if (data.cfml.forwardIfCurrent("nct",false,true)){ expr = decisionOpCreate(data,OPDecision.NCT,expr); hasChanged=true;}    
618                            }
619                            
620                    }
621                    while(hasChanged);
622                    return expr;
623            }
624            private Expression decisionOpCreate(Data data,int operation, Expression left) throws TemplateException {
625            comments(data);
626            return OPDecision.toExprBoolean(left, concatOp(data), operation);
627            }
628    
629            /**
630            * Transfomiert eine  Konkatinations-Operator (&) Operation. Im Gegensatz zu CFMX ,
631            * wird das "!" Zeichen auch als Not Operator anerkannt.
632            * <br />
633            * EBNF:<br />
634            * <code>plusMinusOp {"&" spaces concatOp};</code>
635            * @return CFXD Element
636            * @throws TemplateException 
637            */
638            protected Expression concatOp(Data data) throws TemplateException {
639                    Expression expr = plusMinusOp(data);
640                    
641                    while(data.cfml.isCurrent('&') && !data.cfml.isCurrent("&&")) {
642                            data.cfml.next();
643                            
644                            // &=
645                            if (data.cfml.isCurrent('=') && expr instanceof Variable) {
646                                    data.cfml.next();
647                                    comments(data);
648                                    Expression right = assignOp(data);
649                                    ExprString res = OpString.toExprString(expr, right);
650                                    expr=new OpVariable((Variable)expr,res);
651                            }
652                            else {
653                        comments(data);
654                        expr=OpString.toExprString(expr, plusMinusOp(data));
655                            }
656                            
657                    }
658                    return expr;
659            }
660    
661            /**
662            * Transfomiert die mathematischen Operatoren Plus und Minus (1,-).
663            * <br />
664            * EBNF:<br />
665            * <code>modOp [("-"|"+") spaces plusMinusOp];</code>
666            * @return CFXD Element
667            * @throws TemplateException 
668            */
669            protected Expression plusMinusOp(Data data) throws TemplateException {
670                    Expression expr = modOp(data);
671                    
672                    while(!data.cfml.isLast()) {
673                            
674                            // Plus Operation
675                            if (data.cfml.forwardIfCurrent('+'))                    expr=_plusMinusOp(data,expr,OpDouble.PLUS);
676                            // Minus Operation
677                            else if (data.cfml.forwardIfCurrent('-'))       expr=_plusMinusOp(data,expr,OpDouble.MINUS);
678                            else break;
679                    }
680                    return expr;
681            }
682            
683            
684    
685            private Expression _plusMinusOp(Data data,Expression expr,int opr) throws TemplateException {
686                    // +=
687                    if (data.cfml.isCurrent('=') && expr instanceof Variable) {
688                            data.cfml.next();
689                            comments(data);
690                            Expression right = assignOp(data);
691                            ExprDouble res = OpDouble.toExprDouble(expr, right,opr);
692                            expr=new OpVariable((Variable)expr,res);
693                    }
694                    /*/ ++
695                    else if (data.cfml.isCurrent(opr==OpDouble.PLUS?'+':'-') && expr instanceof Variable) {
696                            data.cfml.next();
697                            comments(data);
698                            ExprDouble res = OpDouble.toExprDouble(expr, LitDouble.toExprDouble(1D,-1),opr);
699                            expr=new OpVariable((Variable)expr,res);
700                            expr=OpDouble.toExprDouble(expr,LitDouble.toExprDouble(1D, -1),opr==OpDouble.PLUS? OpDouble.MINUS:OpDouble.PLUS);
701                            //comments(data);
702                    }*/
703                    else {
704                            comments(data);
705                expr=OpDouble.toExprDouble(expr, modOp(data), opr); 
706                    }
707                    return expr;
708            }
709            
710    
711            /**
712            * Transfomiert eine Modulus Operation. Im Gegensatz zu CFMX ,
713            * wird das "%" Zeichen auch als Modulus Operator anerkannt.
714            * <br />
715            * EBNF:<br />
716            * <code>divMultiOp {("mod" | "%") spaces divMultiOp}; (* modulus operator , "%" Existiert in CFMX nicht *)</code>
717            * @return CFXD Element
718            * @throws TemplateException 
719            */
720            protected Expression modOp(Data data) throws TemplateException {
721                    Expression expr = divMultiOp(data);
722                    
723                    // Modulus Operation
724                    while(data.cfml.forwardIfCurrent('%') || data.cfml.forwardIfCurrentAndNoWordAfter("mod")) {
725                            expr=_modOp(data,expr);
726                            //comments(data);
727                //expr=OpDouble.toExprDouble(expr, divMultiOp(), OpDouble.MODULUS);
728                    }
729                    return expr;
730            }
731            
732            private Expression _modOp(Data data,Expression expr) throws TemplateException {
733                    if (data.cfml.isCurrent('=') && expr instanceof Variable) {
734                            data.cfml.next();
735                            comments(data);
736                            Expression right = assignOp(data);
737                            ExprDouble res = OpDouble.toExprDouble(expr, right,OpDouble.MODULUS);
738                            return new OpVariable((Variable)expr,res);
739                    }
740            comments(data);
741            return OpDouble.toExprDouble(expr, expoOp(data), OpDouble.MODULUS);
742            }
743    
744            /**
745            * Transfomiert die mathematischen Operatoren Mal und Durch (*,/).
746            * <br />
747            * EBNF:<br />
748            * <code>expoOp {("*"|"/") spaces expoOp};</code>
749            * @return CFXD Element
750            * @throws TemplateException 
751            */
752            protected Expression divMultiOp(Data data) throws TemplateException {
753                    Expression expr = expoOp(data);
754    
755                    while (!data.cfml.isLast()) {
756                            
757                                    // Multiply Operation
758                                    if(data.cfml.forwardIfCurrent('*')) {
759                                            expr=_divMultiOp(data,expr,OpDouble.MULTIPLY);
760                                            //comments(data);
761                        //expr=OpDouble.toExprDouble(expr, expoOp(), OpDouble.MULTIPLY);
762                                    }
763                                    // Divide Operation
764                                    else if (data.cfml.isCurrent('/') && (!data.cfml.isCurrent('/','>') )) {
765                                            data.cfml.next(); 
766                                            expr=_divMultiOp(data,expr,OpDouble.DIVIDE);
767                                            //comments(data);
768                        //expr=OpDouble.toExprDouble(expr, expoOp(), OpDouble.DIVIDE);
769                                    }
770                                    // Divide Operation
771                                    else if (data.cfml.isCurrent('\\')) {
772                                            data.cfml.next(); 
773                                            expr=_divMultiOp(data,expr,OpDouble.INTDIV);
774                                            //comments(data);
775                        //expr=OpDouble.toExprDouble(expr, expoOp(), OpDouble.INTDIV);
776                                    }
777                                    else {
778                                            break;
779                                    }
780                            
781                    }
782                    return expr;
783            }
784    
785            private Expression _divMultiOp(Data data,Expression expr, int iOp) throws TemplateException {
786                    if (data.cfml.isCurrent('=') && expr instanceof Variable) {
787                            data.cfml.next();
788                            comments(data);
789                            Expression right = assignOp(data);
790                            ExprDouble res = OpDouble.toExprDouble(expr, right,iOp);
791                            return new OpVariable((Variable)expr,res);
792                    }
793            comments(data);
794            return OpDouble.toExprDouble(expr, expoOp(data), iOp);
795            }
796    
797            /**
798            * Transfomiert den Exponent Operator (^,exp). Im Gegensatz zu CFMX ,
799            * werden die Zeichen " exp " auch als Exponent anerkannt.
800            * <br />
801            * EBNF:<br />
802            * <code>clip {("exp"|"^") spaces clip};</code>
803            * @return CFXD Element
804            * @throws TemplateException 
805            */
806            protected Expression expoOp(Data data) throws TemplateException {
807                    Expression expr = unaryOp(data);
808    
809                    // Modulus Operation
810                    while(data.cfml.forwardIfCurrent('^') || data.cfml.forwardIfCurrentAndNoWordAfter("exp")) {
811                            comments(data);
812                expr=OpDouble.toExprDouble(expr, unaryOp(data), OpDouble.EXP);
813                    }
814                    return expr;
815            }
816            
817            protected Expression unaryOp(Data data) throws TemplateException {
818                    Expression expr = negatePlusMinusOp(data);
819                    
820                    // Plus Operation
821                    if (data.cfml.forwardIfCurrent("++") && expr instanceof Variable)                       
822                            expr=_unaryOp(data,expr,OpDouble.PLUS);
823                    // Minus Operation
824                    else if (data.cfml.forwardIfCurrent("--") && expr instanceof Variable)  
825                            expr=_unaryOp(data,expr,OpDouble.MINUS);
826                    return expr;
827            }
828            
829            private Expression _unaryOp(Data data,Expression expr,int opr) throws TemplateException {
830                    comments(data);
831                    ExprDouble res = OpDouble.toExprDouble(expr, LitDouble.toExprDouble(1D,-1),opr);
832                    expr=new OpVariable((Variable)expr,res);
833                    return OpDouble.toExprDouble(expr,LitDouble.toExprDouble(1D, -1),opr==OpDouble.PLUS? OpDouble.MINUS:OpDouble.PLUS);
834            }
835            
836            
837            
838    
839            /**
840            * Negate Numbers
841            * @return CFXD Element
842            * @throws TemplateException 
843            */
844            protected Expression negatePlusMinusOp(Data data) throws TemplateException {
845                    // And Operation
846                    int line=data.cfml.getLine();
847                    if (data.cfml.forwardIfCurrent('-')) {
848                            if (data.cfml.forwardIfCurrent('-')) {
849                                    comments(data);
850                                    Expression expr = clip(data);
851                                    ExprDouble res = OpDouble.toExprDouble(expr, LitDouble.toExprDouble(1D,-1),OpDouble.MINUS);
852                                    return new OpVariable((Variable)expr,res);
853                            }
854                            comments(data);
855                            return OpNegateNumber.toExprDouble(clip(data),OpNegateNumber.MINUS,line);
856                            
857                    }
858                    else if (data.cfml.forwardIfCurrent('+')) {
859                            if (data.cfml.forwardIfCurrent('+')) {
860                                    comments(data);
861                                    Expression expr = clip(data);
862                                    ExprDouble res = OpDouble.toExprDouble(expr, LitDouble.toExprDouble(1D,-1),OpDouble.PLUS);
863                                    return new OpVariable((Variable)expr,res);
864                            }
865                            comments(data);
866                            return CastDouble.toExprDouble(clip(data));//OpNegateNumber.toExprDouble(clip(),OpNegateNumber.PLUS,line);
867                    }
868                    return clip(data);
869            }
870    
871            /**
872            * Verarbeitet Ausdrcke die inerhalb einer Klammer stehen.
873            * <br />
874            * EBNF:<br />
875            * <code>("(" spaces impOp ")" spaces) | checker;</code>
876            * @return CFXD Element
877            * @throws TemplateException 
878            */
879            protected Expression clip(Data data) throws TemplateException {
880                return checker(data);
881            }
882            /**
883            * Hier werden die verschiedenen M￶glichen Werte erkannt 
884            * und jenachdem wird mit der passenden Methode weitergefahren
885            * <br />
886            * EBNF:<br />
887            * <code>string | number | dynamic | sharp;</code>
888            * @return CFXD Element
889            * @throws TemplateException 
890            */
891            protected Expression checker(Data data) throws TemplateException {
892                    Expression expr=null;
893                    // String
894                            if((expr=string(data))!=null) {
895                                    expr = subDynamic(data,expr);
896                                    data.mode=STATIC;//(expr instanceof Literal)?STATIC:DYNAMIC;// STATIC
897                                    return expr;
898                            } 
899                    // Number
900                            if((expr=number(data))!=null) {
901                                    expr = subDynamic(data,expr);
902                                    data.mode=STATIC;//(expr instanceof Literal)?STATIC:DYNAMIC;// STATIC
903                                    return expr;
904                            } 
905                    // Dynamic
906                            if((expr=dynamic(data))!=null) {
907                                    expr = newOp(data, expr);
908                                    //if(res==expr)
909                                            expr = subDynamic(data,expr);
910                                    //else expr=res;
911                                    data.mode=DYNAMIC;
912                                    return expr;
913                            } 
914                    // Sharp
915                            if((expr=sharp(data))!=null) {
916                                    data.mode=DYNAMIC;
917                                    return expr;
918                            } 
919                    // JSON
920                            if((expr=json(data,JSON_ARRAY,'[',']'))!=null) {
921                                    data.mode=DYNAMIC;
922                                    return expr;
923                            } 
924                            if((expr=json(data,JSON_STRUCT,'{','}'))!=null) {
925                                    data.mode=DYNAMIC;
926                                    return expr;
927                            } 
928                    // else Error
929                            throw new TemplateException(data.cfml,"Syntax Error, Invalid Construct");       
930            }
931            
932            protected Expression variable(Data data) throws TemplateException {
933                    Expression expr=null;
934                    
935                    // Dynamic
936                    if((expr=dynamic(data))!=null) {
937                            expr = subDynamic(data,expr);
938                            data.mode=DYNAMIC;
939                            return expr;
940                    } 
941                    return null;
942            }
943            
944            /**
945            * Transfomiert einen lierale Zeichenkette.
946            * <br />
947            * EBNF:<br />
948            * <code>("'" {"##"|"''"|"#" impOp "#"| ?-"#"-"'" } "'") | 
949                             (""" {"##"|""""|"#" impOp "#"| ?-"#"-""" } """);</code>
950             * @param data 
951            * @return CFXD Element
952            * @throws TemplateException 
953            */
954            protected Expression string(Data data) throws TemplateException {
955                    
956                    // check starting character for a string literal
957                    if(!data.cfml.isCurrent('"')&& !data.cfml.isCurrent('\''))
958                            return null;
959                    int line=data.cfml.getLine();
960                    
961                    // Init Parameter
962                    char quoter = data.cfml.getCurrentLower();
963                    StringBuffer str=new StringBuffer();
964                    Expression expr=null;
965                    
966                    while(data.cfml.hasNext()) {
967                            data.cfml.next();
968                            // check sharp
969                            if(data.cfml.isCurrent('#')) {
970                                    
971                                    // Ecaped sharp
972                                    if(data.cfml.isNext('#')){
973                                            data.cfml.next();
974                                            str.append('#');
975                                    }
976                                    // get Content of sharp
977                                    else {
978                                            data.cfml.next();
979                        comments(data);
980                                            Expression inner=assignOp(data);
981                        comments(data);
982                                            if (!data.cfml.isCurrent('#'))
983                                                    throw new TemplateException(data.cfml,"Invalid Syntax Closing [#] not found");
984                                            
985                                            ExprString exprStr=null;
986                                            if(str.length()!=0) {
987                                                    exprStr=new LitString(str.toString(),line);
988                                                    if(expr!=null){
989                                                            expr = OpString.toExprString(expr, exprStr);
990                                                    }
991                                                    else expr=exprStr;
992                                                    str=new StringBuffer();
993                                            }
994                                            if(expr==null) {
995                                                    expr=inner;
996                                            }
997                                            else  {
998                                                    expr = OpString.toExprString(expr, inner);
999                                            }       
1000                                    }
1001                            }
1002                            // check quoter
1003                            else if(data.cfml.isCurrent(quoter)) {
1004                                    // Ecaped sharp
1005                                    if(data.cfml.isNext(quoter)){
1006                                            data.cfml.next();
1007                                            str.append(quoter);
1008                                    }
1009                                    // finsish
1010                                    else {
1011                                            break;
1012                                    }                               
1013                            }
1014                            // all other character
1015                            else {
1016                                    str.append(data.cfml.getCurrent());
1017                            }
1018                    }
1019                    if(!data.cfml.forwardIfCurrent(quoter))
1020                            throw new TemplateException(data.cfml,"Invalid Syntax Closing ["+quoter+"] not found");
1021                    
1022                    if(expr==null)
1023                            expr=new LitString(str.toString(),line);
1024                    else if(str.length()!=0) {
1025                            expr = OpString.toExprString(expr, new LitString(str.toString(),line));
1026                    }
1027            comments(data);
1028                    return expr;
1029                    
1030            }
1031    
1032            /**
1033            * Transfomiert einen numerische Wert. 
1034            * Die L¦nge des numerischen Wertes interessiert nicht zu ᅵbersetzungszeit, 
1035            * ein "Overflow" fhrt zu einem Laufzeitfehler. 
1036            * Da die zu erstellende CFXD, bzw. dieser Transfomer, keine Vorwegnahme des Laufzeitsystems vornimmt. 
1037            * <br />
1038            * EBNF:<br />
1039            * <code>["+"|"-"] digit {digit} {"." digit {digit}};</code>
1040            * @return CFXD Element
1041            * @throws TemplateException 
1042            */
1043            protected LitDouble number(Data data) throws TemplateException {
1044                    // check first character is a number literal representation
1045                    if(!(data.cfml.isCurrentBetween('0','9') || data.cfml.isCurrent('.'))) return null;
1046                    
1047                    int line=data.cfml.getLine();
1048                    StringBuffer rtn=new StringBuffer();
1049                    
1050                    // get digit on the left site of the dot
1051                    if(data.cfml.isCurrent('.')) rtn.append('0');
1052                    else rtn.append(digit(data));
1053                    // read dot if exist
1054                    if(data.cfml.forwardIfCurrent('.')) {
1055                            rtn.append('.');
1056                            String rightSite=digit(data);
1057                            if(rightSite.length()> 0 && data.cfml.forwardIfCurrent('e')) {
1058                                    Boolean expOp=null;
1059                                    if(data.cfml.forwardIfCurrent('+')) expOp=Boolean.TRUE;
1060                                    else if(data.cfml.forwardIfCurrent('-')) expOp=Boolean.FALSE;
1061                                    
1062                                    if(data.cfml.isCurrentBetween('0','9')) {
1063                                            if(expOp==Boolean.FALSE) rightSite+="e-";
1064                                            else if(expOp==Boolean.TRUE) rightSite+="e+";
1065                                            else rightSite+="e";
1066                                    rightSite+=digit(data);
1067                                }
1068                                else {
1069                                    if(expOp!=null) data.cfml.previous();
1070                                    data.cfml.previous();
1071                                }
1072                            }
1073                            // read right side of the dot
1074                            if(rightSite.length()==0)
1075                                    rightSite="0";//throw new TemplateException(cfml, "Number can't end with [.]"); // DIFF 23
1076                            rtn.append(rightSite);
1077                    }
1078            comments(data);
1079            
1080                    try {
1081                            return new LitDouble(Caster.toDoubleValue(rtn.toString()),line);
1082                    } catch (CasterException e) {
1083                            throw new TemplateException(data.cfml,e.getMessage());
1084                    }
1085                    
1086            }
1087            
1088            
1089            
1090            /**
1091            * Liest die reinen Zahlen innerhalb des CFMLString aus und gibt diese als Zeichenkette zurck. 
1092            * <br />
1093            * EBNF:<br />
1094            * <code>"0"|..|"9";</code>
1095            * @return digit Ausgelesene Zahlen als Zeichenkette.
1096            */
1097            protected String digit(Data data) {
1098                    String rtn="";
1099                    while (data.cfml.isValidIndex()) {
1100                            if(!data.cfml.isCurrentBetween('0','9'))break;
1101                            rtn+=data.cfml.getCurrentLower();
1102                            data.cfml.next();
1103                    }
1104                    return rtn;
1105            }
1106    
1107            /**
1108            * Liest den folgenden idetifier ein und prft ob dieser ein boolscher Wert ist. 
1109            * Im Gegensatz zu CFMX wird auch "yes" und "no" als bolscher <wert akzeptiert, 
1110            * was bei CFMX nur beim Umwandeln einer Zeichenkette zu einem boolschen Wert der Fall ist.<br />
1111            * Wenn es sich um keinen bolschen Wert handelt wird der folgende Wert eingelesen mit seiner ganzen Hirarchie.
1112            * <br />
1113            * EBNF:<br />
1114            * <code>"true" | "false" | "yes" | "no" | startElement {("." identifier | "[" structElement "]" )[function] };</code>
1115            * @return CFXD Element
1116            * @throws TemplateException 
1117            */
1118            protected Expression dynamic(Data data) throws TemplateException {
1119                    // Die Implementation weicht ein wenig von der Grammatik ab, 
1120                    // aber nicht in der Logik sondern rein wie es umgesetzt wurde.
1121                    
1122                
1123                
1124                    // get First Element of the Variable
1125                    int line=data.cfml.getLine();
1126                    String name = identifier(data,false,true);
1127                    if(name == null) {
1128                        if (!data.cfml.forwardIfCurrent('(')) return null;
1129                        
1130                comments(data);
1131                            Expression expr = assignOp(data);
1132    
1133                            if (!data.cfml.forwardIfCurrent(')'))
1134                                    throw new TemplateException(
1135                                            data.cfml,
1136                                            "Invalid Syntax Closing [)] not found");
1137                comments(data);
1138                return expr;//subDynamic(expr);
1139                
1140                    }
1141                            
1142                    Variable var;
1143            comments(data);
1144                    
1145                    // Boolean constant 
1146                    if(name.equals("TRUE")) {// || name.equals("YES"))      {
1147                            comments(data);
1148                            return new LitBoolean(true,line);
1149                    }
1150                    else if(name.equals("FALSE"))   {// || name.equals("NO"))       {
1151                            comments(data);
1152                            return new LitBoolean(false,line);
1153                    }
1154                    
1155                    // Extract Scope from the Variable
1156                    //int c=data.cfml.getColumn();
1157                    int l=data.cfml.getLine();
1158                    var = startElement(data,name,line);
1159                    var.setLine(l);
1160                    
1161                    return var;
1162            }
1163            
1164    
1165            
1166            protected Expression json(Data data,FunctionLibFunction flf, char start, char end) throws TemplateException {
1167                    if(!data.cfml.forwardIfCurrent(start))return null;
1168                    
1169                    int line = data.cfml.getLine();
1170                    BIF bif=new BIF(flf.getName(),flf);
1171                    bif.setArgType(flf.getArgType());
1172                    bif.setClassName(flf.getCls());
1173                    bif.setReturnType(flf.getReturnTypeAsString());
1174                    
1175                    do {
1176                            comments(data);
1177                            if (data.cfml.isCurrent(end))break;
1178                            
1179                            bif.addArgument(functionArgument(data));
1180                            comments(data);
1181                    } 
1182                    while (data.cfml.forwardIfCurrent(','));
1183                    comments(data);
1184                            
1185                    if (!data.cfml.forwardIfCurrent(end))
1186                            throw new TemplateException(data.cfml,"Invalid Syntax Closing ["+end+"] not found");
1187                    comments(data);
1188                    Variable var=new Variable(line);
1189                    var.addMember(bif);
1190                    return var;
1191            }
1192            
1193    
1194            
1195            
1196            protected FunctionLibFunction getFLF(Data data,String name) {
1197                    FunctionLibFunction flf=null;
1198                    for (int i = 0; i < data.fld.length; i++) {
1199                            flf = data.fld[i].getFunction(name);
1200                            if (flf != null)
1201                                    break;
1202                    }
1203                    return flf;
1204            }
1205    
1206            private Expression subDynamic(Data data,Expression expr) throws TemplateException {
1207                    
1208                    
1209                    
1210    
1211                String name=null;
1212                Invoker invoker=null;
1213                    // Loop over nested Variables
1214                    while (data.cfml.isValidIndex()) {
1215                            Expression nameProp = null,namePropUC = null;
1216                            // .
1217                            if (data.cfml.forwardIfCurrent('.')) {
1218                                    // Extract next Var String
1219                    comments(data);
1220                    int line=data.cfml.getLine();
1221                                    name = identifier(data,true,false);
1222                                    if(name==null) 
1223                                            throw new TemplateException(data.cfml, "Invalid identifier");
1224                    comments(data);
1225                                    nameProp=LitString.toExprString(name,line);
1226                                    namePropUC=LitString.toExprString(name.toUpperCase(),line);
1227                            }
1228                            // []
1229                            else if (data.cfml.forwardIfCurrent('[')) {
1230                                    
1231                                    // get Next Var
1232                                    nameProp = structElement(data);
1233                                    namePropUC=nameProp;
1234                                    // Valid Syntax ???
1235                                    if (!data.cfml.forwardIfCurrent(']'))
1236                                            throw new TemplateException(
1237                                                    data.cfml,
1238                                                    "Invalid Syntax Closing []] not found");
1239                            }
1240                            /* / :
1241                            else if (data.cfml.forwardIfCurrent(':')) {
1242                                    // Extract next Var String
1243                    comments(data);
1244                    int line=data.cfml.getLine();
1245                                    name = identifier(true,true);
1246                                    if(name==null) 
1247                                            throw new TemplateException(cfml, "Invalid identifier");
1248                    comments(data);
1249                    
1250                                    nameProp=LitString.toExprString(name,line);
1251                            }*/
1252                            // finish
1253                            else {
1254                                    break;
1255                            }
1256    
1257                comments(data);
1258                
1259                if(expr instanceof Invoker)  {
1260                    invoker=(Invoker) expr;
1261                }
1262                else {
1263                    invoker=new ExpressionInvoker(expr);
1264                    expr=invoker;
1265                }
1266                            // Method
1267                            if (data.cfml.isCurrent('(')) invoker.addMember(getFunctionMember(data,name, false, nameProp));
1268                            
1269                            // property
1270                            else invoker.addMember(new DataMember(namePropUC));
1271                            
1272                    }
1273                    
1274                    return expr;  
1275            }
1276            
1277            private Expression newOp(Data data,Expression expr) throws TemplateException {
1278                    if(!(expr instanceof Variable)) return expr;
1279                    Variable var=(Variable) expr;
1280                    Member m= var.getFirstMember();
1281                    if(!(m instanceof DataMember)) return expr;
1282                    
1283                    ExprString n = ((DataMember)m).getName();
1284                    if(!(n instanceof LitString)) return expr;
1285                    
1286                    LitString ls=(LitString) n;
1287                    
1288                    
1289                    if(!"new".equalsIgnoreCase(ls.getString())) return expr;
1290                    
1291                    int start=data.cfml.getPos();
1292                String name=null;
1293                
1294                
1295                // first identifier
1296                name = identifier(data,true,false);
1297                
1298                    
1299                    ExprString exprName;
1300                    if(name!=null)  {
1301                            StringBuilder fullName=new StringBuilder();
1302                            fullName.append(name);
1303                            // Loop over addional identifier
1304                            while (data.cfml.isValidIndex()) {
1305                                    if (data.cfml.forwardIfCurrent('.')) {
1306                                            comments(data);
1307                            name = identifier(data,true,false);
1308                                            if(name==null) {
1309                                                    data.cfml.setPos(start);
1310                                                    return expr;//throw new TemplateException(data.cfml,"invalid Component declaration ");
1311                                            }
1312                                            fullName.append('.');
1313                                            fullName.append(name);
1314                                            comments(data);
1315                                    }
1316                                    else break;
1317                            }
1318                            
1319                            exprName=LitString.toExprString(fullName.toString());
1320                    }
1321                    else {
1322                            
1323                            Expression str=string(data);
1324                            if(str!=null){
1325                                    exprName=CastString.toExprString(str);
1326                            }
1327                            else {
1328                                    data.cfml.setPos(start);
1329                                    return expr;
1330                            }
1331                    }
1332    
1333            comments(data);
1334            
1335            if (data.cfml.isCurrent('(')) {
1336                            FunctionMember func = getFunctionMember(data,"_createComponent", true, null);
1337                            func.addArgument(new Argument(exprName,"string"));
1338                            Variable v=new Variable(expr.getLine());
1339                            v.addMember(func);
1340                comments(data);
1341                            return v;
1342                    } 
1343            data.cfml.setPos(start);
1344            return expr;//throw new TemplateException(data.cfml,"invalid Component declaration ");
1345                    
1346            }
1347            
1348            
1349            
1350            
1351            
1352            /**
1353            * Extrahiert den Start Element einer Variale, 
1354            * dies ist entweder eine Funktion, eine Scope Definition oder eine undefinierte Variable. 
1355            * <br />
1356            * EBNF:<br />
1357            * <code>identifier "(" functionArg ")" | scope | identifier;</code>
1358            * @param name Einstiegsname
1359            * @return CFXD Element
1360            * @throws TemplateException 
1361            */
1362            protected Variable startElement(Data data,String name, int line) throws TemplateException {
1363                    
1364                    
1365                    
1366                    String lc = name;
1367                    
1368                    // check function
1369                    if (data.cfml.isCurrent('(')) {
1370                            FunctionMember func = getFunctionMember(data,lc, true, null);
1371                            
1372                            Variable var=new Variable(line);
1373                            var.addMember(func);
1374                comments(data);
1375                            return var;
1376                    } 
1377                    
1378                    //check scope
1379                    Variable var = scope(data,lc,line);
1380                    if(var!=null) return var;
1381                    
1382                    // undefined variable
1383                    var=new Variable(line);
1384                    var.addMember(new DataMember(LitString.toExprString(name, data.cfml.getLine())));
1385    
1386            comments(data);
1387                    return var;
1388                    
1389            }
1390            
1391            /**
1392            * Liest einen CFML Scope aus, 
1393            * falls der folgende identifier keinem Scope entspricht, 
1394            * gibt die Variable null zurck.
1395            * <br />
1396            * EBNF:<br />
1397            * <code>"variable" | "cgi" | "url" | "form" | "session" | "application" | "arguments" | "cookie" | " client";</code>
1398             * @param idStr String identifier, 
1399             * wird aus Optimierungszwechen nicht innerhalb dieser Funktion ausgelsen.
1400             * @return CFXD Variable Element oder null
1401             * @throws TemplateException 
1402            */
1403            protected Variable scope(Data data,String idStr, int line) throws TemplateException {
1404                    if(data.ignoreScopes)return null;
1405                    if (idStr.equals("CGI"))                                return new Variable(Scope.SCOPE_CGI,line);
1406                    else if (idStr.equals("ARGUMENTS"))     return new Variable(Scope.SCOPE_ARGUMENTS,line);
1407                    else if (idStr.equals("REQUEST"))               return new Variable(Scope.SCOPE_REQUEST,line);
1408                    else if (idStr.equals("SESSION"))               return new Variable(Scope.SCOPE_SESSION,line);
1409                    else if (idStr.equals("APPLICATION"))   return new Variable(Scope.SCOPE_APPLICATION,line);
1410                    else if (idStr.equals("VARIABLES"))             return new Variable(Scope.SCOPE_VARIABLES,line);
1411                    else if (idStr.equals("FORM"))                  return new Variable(Scope.SCOPE_FORM,line);
1412                    else if (idStr.equals("URL"))                   return new Variable(Scope.SCOPE_URL,line);
1413                    else if (idStr.equals("SERVER"))                return new Variable(Scope.SCOPE_SERVER,line);
1414                    else if (idStr.equals("CLIENT"))                return new Variable(Scope.SCOPE_CLIENT,line);
1415                    else if (idStr.equals("COOKIE"))                return new Variable(Scope.SCOPE_COOKIE,line);
1416                    else if (idStr.equals("CLUSTER"))               return new Variable(Scope.SCOPE_CLUSTER,line);
1417                    else if (idStr.equals("LOCAL"))                 return new Variable(Scope.SCOPE_LOCAL,line);
1418                    else if (idStr.equals("VAR")) {
1419                            String name=identifier(data,false,true);
1420                            if(name!=null){
1421                                    comments(data);
1422                                    Variable local = new Variable(ScopeSupport.SCOPE_VAR,line);
1423                                    if(!"LOCAL".equals(name))local.addMember(new DataMember(LitString.toExprString(name, data.cfml.getLine())));
1424                                    else {
1425                                            local.ignoredFirstMember(true);
1426                                    }
1427                                    return local;
1428                            }
1429                    } 
1430                    return null;
1431            }
1432        
1433            /**
1434            * Liest einen Identifier aus und gibt diesen als String zurck.
1435            * <br />
1436            * EBNF:<br />
1437            * <code>(letter | "_") {letter | "_"|digit};</code>
1438             * @param firstCanBeNumber 
1439             * @param lowerCase 
1440            * @return Identifier.
1441            */
1442            protected String identifier(Data data,boolean firstCanBeNumber,boolean upper) {
1443                    int start = data.cfml.getPos();
1444                    if(!data.cfml.isCurrentLetter() && !data.cfml.isCurrentSpecial() ) {
1445                        if(!firstCanBeNumber) return null;
1446                else if(!data.cfml.isCurrentBetween('0','9'))return null;
1447            }
1448                    do {
1449                            data.cfml.next();
1450                            if(!(data.cfml.isCurrentLetter()
1451                                    || data.cfml.isCurrentBetween('0','9')
1452                                    || data.cfml.isCurrentSpecial())) {
1453                                            break;
1454                                    }
1455                    }
1456                    while (data.cfml.isValidIndex());
1457                    if(upper)
1458                            return data.cfml.substring(start,data.cfml.getPos()-start).toUpperCase();
1459                    
1460                    return data.cfml.substring(start,data.cfml.getPos()-start);
1461            }
1462    
1463            /**
1464            * Transfomiert ein Collection Element das in eckigen Klammern aufgerufen wird. 
1465            * <br />
1466            * EBNF:<br />
1467            * <code>"[" impOp "]"</code>
1468            * @return CFXD Element
1469            * @throws TemplateException 
1470            */
1471            protected Expression structElement(Data data) throws TemplateException {
1472            comments(data);
1473                    Expression name = CastString.toExprString(assignOp(data));
1474                    if(name instanceof LitString)((LitString)name).fromBracket(true);
1475            comments(data);
1476                    return name;
1477            }
1478    
1479            /**
1480            * Liest die Argumente eines Funktonsaufruf ein und prft ob die Funktion 
1481            * innerhalb der FLD (Function Library Descriptor) definiert ist. 
1482            * Falls sie existiert wird die Funktion gegen diese geprft und ein build-in-function CFXD Element generiert, 
1483            * ansonsten ein normales funcion-call Element.
1484            * <br />
1485            * EBNF:<br />
1486            * <code>[impOp{"," impOp}];</code>
1487            * @param name Identifier der Funktion als Zeichenkette
1488            * @param checkLibrary Soll geprft werden ob die Funktion innerhalb der Library existiert.
1489            * @param nameProp Identifier als CFXD Element, wenn dieses null ist wird es ignoriert.
1490            * @return CFXD Element
1491            * @throws TemplateException 
1492            */
1493            protected FunctionMember getFunctionMember(Data data,
1494                    String name,
1495                    boolean checkLibrary,
1496                    Expression exprName)
1497                    throws TemplateException {
1498    
1499                    // get Function Library
1500                    checkLibrary=checkLibrary && data.fld!=null;
1501                    FunctionLibFunction flf = null;
1502                    if (checkLibrary) {
1503                            for (int i = 0; i < data.fld.length; i++) {
1504                                    flf = data.fld[i].getFunction(name);
1505                                    if (flf != null)
1506                                            break;
1507                            }
1508                            if (flf == null) {
1509                                    checkLibrary = false;
1510                            }
1511                    }
1512                    // Element Function
1513                    FunctionMember fm;
1514                    if(checkLibrary) {
1515                            BIF bif=new BIF(name,flf);
1516                            bif.setArgType(flf.getArgType());
1517                            bif.setClassName(flf.getCls());
1518                            bif.setReturnType(flf.getReturnTypeAsString());
1519                            fm=bif;
1520                            
1521                            if(flf.getArgType()== FunctionLibFunction.ARG_DYNAMIC && flf.hasDefaultValues()){
1522                            ArrayList args = flf.getArg();
1523                                    Iterator it = args.iterator();
1524                            FunctionLibFunctionArg arg;
1525                            while(it.hasNext()){
1526                                    arg=(FunctionLibFunctionArg) it.next();
1527                                    if(arg.getDefaultValue()!=null)
1528                                            bif.addArgument(
1529                                                            new NamedArgument(
1530                                                                            LitString.toExprString(arg.getName()),
1531                                                                            LitString.toExprString(arg.getDefaultValue()),
1532                                                                            arg.getTypeAsString()
1533                                                                            ));
1534                            }
1535                            }
1536                    }
1537                    else {
1538                            if(exprName==null)fm = new UDF(name);
1539                            else fm = new UDF(exprName);
1540                    }
1541                    
1542                    
1543                    
1544    
1545                    // Function Attributes
1546                    ArrayList arrFuncLibAtt = null;
1547                    int libLen = 0;
1548                    if (checkLibrary) {
1549                            arrFuncLibAtt = flf.getArg();
1550                            libLen = arrFuncLibAtt.size();
1551                    }
1552                    int count = 0;
1553                    do {
1554                            data.cfml.next();
1555                comments(data);
1556    
1557                            // finish
1558                            if (count==0 && data.cfml.isCurrent(')'))
1559                                    break;
1560    
1561                            // too many Attributes
1562                            boolean isDynamic=false;
1563                            int max=-1;
1564                            if(checkLibrary) {
1565                                    isDynamic=flf.getArgType()==FunctionLibFunction.ARG_DYNAMIC;
1566                                    max=flf.getArgMax();
1567                            // Dynamic
1568                                    if(isDynamic) {
1569                                            if(max!=-1 && max <= count)
1570                                                    throw new TemplateException(
1571                                                            data.cfml,
1572                                                            "too many Attributes in function [" + name + "]");
1573                                    }
1574                            // Fix
1575                                    else {
1576                                            if(libLen <= count){
1577                                                    
1578                                                    TemplateException te = new TemplateException(
1579                                                            data.cfml,
1580                                                            "too many Attributes in function call [" + name + "]");
1581                                                    addFunctionDoc(te, flf);
1582                                                    throw te;
1583                                            }
1584                                    }
1585                                    
1586                            }
1587                            
1588                            //Argument arg;
1589                            if (checkLibrary && !isDynamic) {
1590                                    // current attribues from library
1591                                    FunctionLibFunctionArg funcLibAtt =(FunctionLibFunctionArg) arrFuncLibAtt.get(count);
1592                                    fm.addArgument(functionArgument(data,funcLibAtt.getTypeAsString()));    
1593                            } 
1594                            else {
1595                                    fm.addArgument(functionArgument(data));
1596                            }
1597    
1598                comments(data);
1599                            count++;
1600                            if (data.cfml.isCurrent(')'))
1601                                    break;
1602                    } 
1603                    while (data.cfml.isCurrent(','));
1604    
1605                    // end with ) ??                
1606                    if (!data.cfml.forwardIfCurrent(')'))
1607                            throw new TemplateException(
1608                                    data.cfml,
1609                                    "Invalid Syntax Closing [)] for function ["
1610                                            + name
1611                                            + "] not found");
1612    
1613                    // check min attributes
1614                    if (checkLibrary && flf.getArgMin() > count){
1615                            TemplateException te = new TemplateException(
1616                                    data.cfml,
1617                                    "too few attributes in function [" + name + "]");
1618                            if(flf.getArgType()==FunctionLibFunction.ARG_FIX) addFunctionDoc(te, flf);
1619                            throw te;
1620                    }
1621    
1622            comments(data);
1623            
1624            // evaluator
1625            if(checkLibrary && flf.hasTteClass()){
1626                    flf.getEvaluator().evaluate((BIF) fm, flf);
1627            }
1628            
1629                    return fm;
1630            }
1631            
1632            public static void addFunctionDoc(PageExceptionImpl pe,FunctionLibFunction flf) {
1633                    ArrayList<FunctionLibFunctionArg> args=flf.getArg();
1634                    Iterator<FunctionLibFunctionArg> it = args.iterator();
1635                    
1636                    // Pattern
1637                    StringBuilder pattern=new StringBuilder(flf.getName());
1638                    StringBuilder end=new StringBuilder();
1639                    pattern.append("(");
1640                    FunctionLibFunctionArg arg;
1641                    int c=0;
1642                    while(it.hasNext()){
1643                            arg = it.next();
1644                            if(!arg.isRequired()) {
1645                                    pattern.append(" [");
1646                                    end.append("]");
1647                            }
1648                            if(c++>0)pattern.append(", ");
1649                            pattern.append(arg.getName());
1650                            pattern.append(":");
1651                            pattern.append(arg.getType());
1652                            
1653                    }
1654                    pattern.append(end);
1655                    pattern.append("):");
1656                    pattern.append(flf.getReturnTypeAsString());
1657                    
1658                    pe.setAdditional("Pattern", pattern);
1659                    
1660                    // Documentation
1661                    StringBuilder doc=new StringBuilder(flf.getDescription());
1662                    StringBuilder req=new StringBuilder();
1663                    StringBuilder opt=new StringBuilder();
1664                    StringBuilder tmp;
1665                    doc.append("\n");
1666                    
1667                    it = args.iterator();
1668                    while(it.hasNext()){
1669                            arg = it.next();
1670                            tmp=arg.isRequired()?req:opt;
1671                            
1672                            tmp.append("- ");
1673                            tmp.append(arg.getName());
1674                            tmp.append(" (");
1675                            tmp.append(arg.getType());
1676                            tmp.append("): ");
1677                            tmp.append(arg.getDescription());
1678                            tmp.append("\n");
1679                    }
1680    
1681                    if(req.length()>0)doc.append("\nRequired:\n").append(req);
1682                    if(opt.length()>0)doc.append("\nOptional:\n").append(opt);
1683                    
1684                    
1685                    pe.setAdditional("Documentation", doc);
1686                    
1687            }
1688    
1689            /**
1690             * Sharps (#) die innerhalb von Expressions auftauchen haben in CFML keine weitere Beteutung 
1691             * und werden durch diese Methode einfach entfernt.
1692             * <br />
1693             * Beispiel:<br />
1694             * <code>arrayLen(#arr#)</code> und <code>arrayLen(arr)</code> sind identisch.
1695             * EBNF:<br />
1696             * <code>"#" checker "#";</code>
1697             * @return CFXD Element
1698             * @throws TemplateException 
1699            */
1700            protected Expression sharp(Data data) throws TemplateException {
1701                    if(!data.cfml.forwardIfCurrent('#'))
1702                            return null;
1703                    Expression expr;
1704            comments(data);
1705            boolean old=data.allowLowerThan;
1706            data.allowLowerThan=true;
1707                    expr = assignOp(data);
1708                    data.allowLowerThan=old;
1709            comments(data);
1710                    if (!data.cfml.forwardIfCurrent('#'))
1711                            throw new TemplateException(
1712                                    data.cfml,
1713                                    "Syntax Error, Invalid Construct "+(data.cfml.length()<30?data.cfml.toString():""));
1714            comments(data);
1715                    return expr;
1716            }
1717            
1718            /**
1719             * @param data 
1720             * @return parsed Element
1721             * @throws TemplateException
1722             */
1723            private Expression simple(Data data,String[] breakConditions) throws TemplateException {
1724                    StringBuffer sb=new StringBuffer();
1725                    int line=data.cfml.getLine();
1726                    outer:while(data.cfml.isValidIndex()) {
1727                            for(int i=0;i<breakConditions.length;i++){
1728                                    if(data.cfml.isCurrent(breakConditions[i]))break outer;
1729                            }
1730                            
1731                            //if(data.cfml.isCurrent(' ') || data.cfml.isCurrent('>') || data.cfml.isCurrent("/>")) break;
1732                            
1733                            if(data.cfml.isCurrent('"') || data.cfml.isCurrent('#') || data.cfml.isCurrent('\'')) {
1734                                    throw new TemplateException(data.cfml,"simple attribute value can't contain ["+data.cfml.getCurrent()+"]");
1735                            }
1736                            else sb.append(data.cfml.getCurrent());
1737                            data.cfml.next();
1738                    }
1739            comments(data);
1740                    
1741                    return LitString.toExprString(sb.toString(),line);
1742            }
1743        
1744    
1745        /**
1746         *  Liest alle folgenden Komentare ein.
1747          * <br />
1748         * EBNF:<br />
1749         * <code>{?-"\n"} "\n";</code>
1750         * @param data 
1751         * @throws TemplateException
1752         */
1753        protected void comments(Data data) throws TemplateException {
1754            data.cfml.removeSpace();
1755            while(comment(data)){data.cfml.removeSpace();}
1756        }
1757        
1758        /**
1759         *  Liest einen Einzeiligen Kommentar ein.
1760          * <br />
1761         * EBNF:<br />
1762         * <code>{?-"\n"} "\n";</code>
1763         * @return bool Wurde ein Kommentar entfernt?
1764         * @throws TemplateException
1765         */
1766        protected boolean comment(Data data) throws TemplateException {
1767            if(singleLineComment(data.cfml) || multiLineComment(data) || CFMLTransformer.comment(data.cfml)) return true;
1768            return false;
1769        }
1770    
1771        /**
1772         * Liest einen Mehrzeiligen Kommentar ein.
1773         * <br />
1774         * EBNF:<br />
1775         * <code>?-"*<!-- -->/";</code>
1776         * @return bool Wurde ein Kommentar entfernt?
1777         * @throws TemplateException
1778         */
1779        private boolean multiLineComment(Data data) throws TemplateException {
1780           CFMLString cfml = data.cfml;
1781            if(!cfml.forwardIfCurrent("/*")) return false;
1782            int pos=cfml.getPos();
1783            boolean isDocComment=cfml.isCurrent('*');
1784            while(cfml.isValidIndex()) {
1785                if(cfml.isCurrent("*/")) break;
1786                cfml.next();
1787            }
1788            if(!cfml.forwardIfCurrent("*/")){
1789                cfml.setPos(pos);
1790                throw new TemplateException(cfml,"comment is not closed");
1791            }
1792            if(isDocComment) {
1793                    String comment = cfml.substring(pos-2,cfml.getPos()-pos);
1794                    data.docComment=docCommentTransformer.transform(comment);
1795            }
1796            return true;
1797        }
1798        
1799        
1800        
1801        /**
1802         *  Liest einen Einzeiligen Kommentar ein.
1803          * <br />
1804         * EBNF:<br />
1805         * <code>{?-"\n"} "\n";</code>
1806         * @return bool Wurde ein Kommentar entfernt?
1807         */
1808        private boolean singleLineComment(CFMLString cfml) {
1809            if(!cfml.forwardIfCurrent("//")) return false;
1810            return cfml.nextLine();
1811        }
1812    
1813            /* *
1814             * @return the ignoreScopes
1815             * /
1816            public boolean isIgnoreScopes() {
1817                    return ignoreScopes;
1818            }*/
1819    
1820            /* *
1821             * @param ignoreScopes the ignoreScopes to set
1822             * /
1823            public void setIgnoreScopes(boolean ignoreScopes) {
1824                    this.ignoreScopes = ignoreScopes;
1825            }*/
1826        
1827    }