001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.scxml2.model; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.apache.commons.scxml2.ActionExecutionContext; 023import org.apache.commons.scxml2.Context; 024import org.apache.commons.scxml2.Evaluator; 025import org.apache.commons.scxml2.SCXMLExpressionException; 026import org.apache.commons.scxml2.TriggerEvent; 027import org.apache.commons.scxml2.semantics.ErrorConstants; 028 029/** 030 * The class in this SCXML object model that corresponds to the 031 * <if> SCXML element, which serves as a container for conditionally 032 * executed elements. <else> and <elseif> can optionally 033 * appear within an <if> as immediate children, and serve to partition 034 * the elements within an <if>. 035 * 036 */ 037public class If extends Action implements ActionsContainer { 038 039 /** 040 * Serial version UID. 041 */ 042 private static final long serialVersionUID = 1L; 043 044 /** 045 * An conditional expression which can be evaluated to true or false. 046 */ 047 private String cond; 048 049 /** 050 * The set of executable elements (those that inheriting from 051 * Action) that are contained in this <if> element. 052 */ 053 private List<Action> actions; 054 055 /** 056 * The boolean value that dictates whether the particular child action 057 * should be executed. 058 */ 059 private boolean execute; 060 061 /** 062 * Constructor. 063 */ 064 public If() { 065 super(); 066 this.actions = new ArrayList<Action>(); 067 this.execute = false; 068 } 069 070 @Override 071 public final String getContainerElementName() { 072 return ELEM_IF; 073 } 074 075 /** 076 * Get the executable actions contained in this <if>. 077 * 078 * @return Returns the actions. 079 */ 080 public final List<Action> getActions() { 081 return actions; 082 } 083 084 /** 085 * Add an Action to the list of executable actions contained in 086 * this <if>. 087 * 088 * @param action The action to add. 089 */ 090 public final void addAction(final Action action) { 091 if (action != null) { 092 this.actions.add(action); 093 } 094 } 095 096 /** 097 * Get the conditional expression. 098 * 099 * @return Returns the cond. 100 */ 101 public final String getCond() { 102 return cond; 103 } 104 105 /** 106 * Set the conditional expression. 107 * 108 * @param cond The cond to set. 109 */ 110 public final void setCond(final String cond) { 111 this.cond = cond; 112 } 113 114 /** 115 * {@inheritDoc} 116 */ 117 @Override 118 public void execute(ActionExecutionContext exctx) throws ModelException, SCXMLExpressionException { 119 EnterableState parentState = getParentEnterableState(); 120 Context ctx = exctx.getContext(parentState); 121 Evaluator eval = exctx.getEvaluator(); 122 ctx.setLocal(getNamespacesKey(), getNamespaces()); 123 Boolean rslt; 124 try { 125 rslt = eval.evalCond(ctx, cond); 126 if (rslt == null) { 127 if (exctx.getAppLog().isDebugEnabled()) { 128 exctx.getAppLog().debug("Treating as false because the cond expression was evaluated as null: '" 129 + cond + "'"); 130 } 131 rslt = Boolean.FALSE; 132 } 133 } catch (SCXMLExpressionException e) { 134 rslt = Boolean.FALSE; 135 exctx.getInternalIOProcessor().addEvent(new TriggerEvent(TriggerEvent.ERROR_EXECUTION, TriggerEvent.ERROR_EVENT)); 136 exctx.getErrorReporter().onError(ErrorConstants.EXPRESSION_ERROR, "Treating as false due to error: " 137 + e.getMessage(), this); 138 } 139 execute = rslt; 140 ctx.setLocal(getNamespacesKey(), null); 141 // The "if" statement is a "container" 142 for (Action aa : actions) { 143 if (execute && !(aa instanceof ElseIf)) { 144 aa.execute(exctx); 145 } else if (execute && aa instanceof ElseIf) { 146 break; 147 } else if (aa instanceof Else) { 148 execute = true; 149 } else if (aa instanceof ElseIf) { 150 ctx.setLocal(getNamespacesKey(), getNamespaces()); 151 execute = eval.evalCond(ctx, ((ElseIf) aa).getCond()); 152 ctx.setLocal(getNamespacesKey(), null); 153 } 154 } 155 } 156 157} 158