001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.transformer.bytecode.statement;
020
021import java.util.ArrayList;
022import java.util.Iterator;
023
024import lucee.transformer.bytecode.Body;
025import lucee.transformer.bytecode.BytecodeContext;
026import lucee.transformer.bytecode.BytecodeException;
027import lucee.transformer.bytecode.Position;
028import lucee.transformer.bytecode.Statement;
029import lucee.transformer.bytecode.expression.ExprBoolean;
030import lucee.transformer.bytecode.expression.Expression;
031import lucee.transformer.bytecode.literal.LitBoolean;
032import lucee.transformer.bytecode.util.ExpressionUtil;
033import lucee.transformer.bytecode.visitor.ConditionVisitor;
034
035public final class Condition extends StatementBaseNoFinal implements HasBodies {
036    
037    private ArrayList<Pair> ifs=new ArrayList<Pair>();
038    private Pair _else;
039
040    /**
041     * Constructor of the class
042     * @param condition
043     * @param body
044     * @param line
045     */
046    public Condition(Position start,Position end) {
047        super(start,end);
048    }
049    
050    /**
051     * Constructor of the class
052     * @param condition
053     * @param body
054     * @param line
055     */
056    public Condition(ExprBoolean condition, Statement body, Position start,Position end) {
057        super(start,end);
058        addElseIf(condition,body,start,end);
059        
060        body.setParent(this);
061    }
062    
063    public Condition(boolean b, Statement body, Position start,Position end) {
064                this(LitBoolean.toExprBoolean(b),body,start,end);
065        }
066
067        /**
068     * adds a else statement
069     * @param condition
070     * @param body
071     */
072    public Pair addElseIf(ExprBoolean condition, Statement body, Position start,Position end) {
073        Pair pair;
074        ifs.add(pair=new Pair(condition,body,start,end));
075        body.setParent(this);
076        return pair;
077    }
078    
079    /**
080     * sets the else Block of the condition
081     * @param body
082     */
083    public Pair setElse(Statement body, Position start,Position end) {
084        _else=new Pair(null,body,start,end);
085        body.setParent(this);
086        return _else;
087    }
088    
089    public final class Pair {
090        private ExprBoolean condition;
091        private Statement body;
092        private Position start;
093        public Position end;
094
095        public Pair(ExprBoolean condition, Statement body, Position start,Position end) {
096            this.condition=condition;
097            this.body=body;
098            this.start=start;
099            this.end=end;
100        }
101    }
102    
103    
104
105    public void _writeOut(BytecodeContext bc) throws BytecodeException {
106        Iterator<Pair> it = ifs.iterator();
107        Pair pair;
108        ConditionVisitor cv=new ConditionVisitor();
109        cv.visitBefore();
110                // ifs
111                while(it.hasNext()) {
112                        pair=it.next();
113                        ExpressionUtil.visitLine(bc, pair.start);
114                        cv.visitWhenBeforeExpr();
115                                pair. condition.writeOut(bc,Expression.MODE_VALUE);
116                        cv.visitWhenAfterExprBeforeBody(bc);
117                                pair.body.writeOut(bc);
118                        cv.visitWhenAfterBody(bc);
119                        if(pair.end!=null)ExpressionUtil.visitLine(bc, pair.end);
120                }
121                // else
122                if(_else!=null && _else.body!=null) {
123                        cv.visitOtherviseBeforeBody();
124                                _else.body.writeOut(bc);
125                        cv.visitOtherviseAfterBody();
126                }
127                
128        cv.visitAfter(bc);
129    }
130
131        /**
132         * @see lucee.transformer.bytecode.statement.HasBodies#getBodies()
133         */
134        public Body[] getBodies() {
135                int len=ifs.size(),count=0;
136                if(_else!=null)len++;
137                Body[] bodies=new Body[len];
138                Pair p;
139                Iterator<Pair> it = ifs.iterator();
140                while(it.hasNext()) {
141                        p=it.next();
142                        bodies[count++]=(Body) p.body;
143                }
144                if(_else!=null)bodies[count++]=(Body) _else.body;
145                
146                return bodies;
147        }
148}