Package org.teiid.query.processor.xml

Source Code of org.teiid.query.processor.xml.IfInstruction

/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/

package org.teiid.query.processor.xml;

import static org.teiid.query.analysis.AnalysisRecord.*;

import java.util.ArrayList;
import java.util.List;

import org.teiid.client.plan.PlanNode;
import org.teiid.common.buffer.BlockedException;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.logging.LogManager;


/**
* <p>This instruction holds a List of Criteria, and for each Criteria there is a
* {@link Program} that will be executed.  Therefore, this ProcessorInstruction
* implements an arbitrarily deep if-else if-....else block.</p>
*
* <p>During processing, the Criteria are iterated through, in order.  When one
* evaluates to true, that Criteria's Program is placed on to the
* Program {@link ProcessorEnvironment#getProgramStack stack}, and the loop
* is broken - this simulates the if-else if-... behavior.  An optional
* "else" or "default" Program can be added via the
* {@link #addDefaultChoiceSubProgram addDefaultChoiceSubProgram}
* method - this is the optional "else"
* block at the end of an if-else if-... construct.</p>
*/
public class IfInstruction extends ProcessorInstruction {

    private List thenBlocks;
    private DefaultCondition defaultCondition;

    // State if condition evaluation blocked
    private int conditionIndex = 0;

    /**
     * Constructor for IfInstruction.
     * @param endIf see {@link #getEndIf}
     */
    public IfInstruction() {
        super();
        this.thenBlocks = new ArrayList();
    }
   
    public void addCondition(Condition condition) {
        thenBlocks.add(condition);
    }

    public void setDefaultCondition(DefaultCondition defaultCondition) {
        this.defaultCondition = defaultCondition;
    }

    /**
     * Return the number of "if/else if" clauses and
     * corresponding "then" sub programs in this If Instruction.
     * (Does not include the optional
     * {@link #getElseProgram "else" sub program}).
     * @return number of "then" sub programs
     */
    int getThenCount(){
        return this.thenBlocks.size();
    }

    /**
     * Return the Criteria object representing the "if" or
     * "else if" condition, at the indicated "then" index.
     * Use {@link #getThenCount getThenCount} method to get the
     * number of then sub programs.
     * @param thenCount index into the ordered list of "then" sub programs
     * @return Criteria for the sub program, or null if it is an invalid index
     */
    Condition getThenCondition(int thenCount){
        if (thenCount >=0 && thenCount < this.thenBlocks.size()){
            return (Condition)this.thenBlocks.get(thenCount);
        }
        return null;
    }

    /**
     * Return the sub Program object representing a "then" clause
     * of this "if then else if..." block, at the indicated "then" index.
     * Use {@link #getThenCount getThenCount} method to get the
     * number of then sub programs.
     * @param thenCount index into the ordered list of "then" sub programs
     * @return the "thenCount"th "then" sub program, or null if it is an invalid index
     */
    Program getThenProgram(int thenCount){
        if (thenCount >=0 && thenCount < this.thenBlocks.size()){
            Condition condition = (Condition)this.thenBlocks.get(thenCount);
            return condition.getThenProgram();
        }
        return null;
    }   
   
    /**
     * Returns the optional "else" sub program, which has no criteria
     * but is executed if no other "if/else if" condition evaluates to
     * true.
     * @return else Program, may be null
     */
    Program getElseProgram(){
        return this.defaultCondition.getThenProgram();
    }
 
    /**
     * This instruction will evaluate it's criteria, one by one.  If any evaluate
     * to true, it will push the corresponding sub-program on to the top of the
     * program stack, and break from the loop.  Regardless if whether any criteria
     * evaluate to true, this instruction will increment the program counter of the
     * current program.
     * @see ProcessorInstruction#process(ProcessorEnvironment)
     */
    public XMLContext process(XMLProcessorEnvironment env, XMLContext context)
        throws BlockedException, TeiidComponentException, TeiidProcessingException{

        List thens = this.thenBlocks;
        if (this.defaultCondition != null){
          //add default choice to the end of the List - this will be
          //the "else" at the end of the "if-then-else-if..." structure,
          //and its rsNames will be null

            //the original List must not be modified, so make a copy
            thens = new ArrayList(thenBlocks);
          thens.add(defaultCondition);
        }
       
        Condition condition = null;
        boolean foundTrueCondition = false;

        for(; conditionIndex < thens.size(); conditionIndex++){           
            condition = (Condition)thens.get(conditionIndex);
                            
            // evaluate may block if criteria evaluation blocks
             if(condition.evaluate(env, context)) {
                 foundTrueCondition = true;
                 //break from the loop; only the first "then" Program
                 //whose criteria evaluates to true will be executed
                 break;
             }
           
        }
        conditionIndex = 0;

        // This IF instruction should be processed exactly once, so the
        // program containing the IF instruction needs to have it's
        // counter incremented.
        // NOTE: At this point, if any of the conditions (above) evaluated
        // to true, then a sub program will be pushed (below) onto the
        // stack above this current program.  That's okay.  Still need to
        // increment program counter so this IF instruction is only
        // executed once
        env.incrementCurrentProgramCounter();

        if (foundTrueCondition) {

            //push the "then" Program onto the stack           
            Program thenProgram = condition.getThenProgram();
           
            env.pushProgram(thenProgram, condition.isProgramRecursive());
            LogManager.logTrace(org.teiid.logging.LogConstants.CTX_XML_PLAN, new Object[]{"IF: true condition", condition, "- then program:", thenProgram}); //$NON-NLS-1$ //$NON-NLS-2$
        }
        return context;
    }

    public String toString() {
        return "IF BLOCK:"; //$NON-NLS-1$
    }
   
    public PlanNode getDescriptionProperties() {
        PlanNode props = new PlanNode("CHOICE"); //$NON-NLS-1$

        for (int i = 0; i < this.thenBlocks.size(); i++) {
            Condition condition = (Condition) thenBlocks.get(i);
            PlanNode node = null;
            if(condition instanceof RecurseProgramCondition) {
                node = new PlanNode("RECURSIVE"); //$NON-NLS-1$
                node.addProperty(PROP_CONDITION, condition.toString());
            } else {
                node = condition.getThenProgram().getDescriptionProperties();
                node.addProperty(PROP_CONDITION, ((CriteriaCondition)condition).criteria.toString());
            }
            props.addProperty("Condition " + i, node); //$NON-NLS-1$
        }
       
        if (defaultCondition != null && defaultCondition.getThenProgram() != null){
            props.addProperty(PROP_DEFAULT_PROGRAM, defaultCondition.getThenProgram().getDescriptionProperties());
        }
               
        return props;
    }
}
TOP

Related Classes of org.teiid.query.processor.xml.IfInstruction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.