View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.scxml2.model;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.apache.commons.scxml2.ActionExecutionContext;
23  import org.apache.commons.scxml2.Context;
24  import org.apache.commons.scxml2.Evaluator;
25  import org.apache.commons.scxml2.SCXMLExpressionException;
26  import org.apache.commons.scxml2.TriggerEvent;
27  import org.apache.commons.scxml2.semantics.ErrorConstants;
28  
29  /**
30   * The class in this SCXML object model that corresponds to the
31   * <if> SCXML element, which serves as a container for conditionally
32   * executed elements. <else> and <elseif> can optionally
33   * appear within an <if> as immediate children, and serve to partition
34   * the elements within an <if>.
35   *
36   */
37  public class If extends Action implements ActionsContainer {
38  
39      /**
40       * Serial version UID.
41       */
42      private static final long serialVersionUID = 1L;
43  
44      /**
45       * An conditional expression which can be evaluated to true or false.
46       */
47      private String cond;
48  
49      /**
50       * The set of executable elements (those that inheriting from
51       * Action) that are contained in this <if> element.
52       */
53      private List<Action> actions;
54  
55      /**
56       * The boolean value that dictates whether the particular child action
57       * should be executed.
58       */
59      private boolean execute;
60  
61      /**
62       * Constructor.
63       */
64      public If() {
65          super();
66          this.actions = new ArrayList<Action>();
67          this.execute = false;
68      }
69  
70      @Override
71      public final String getContainerElementName() {
72          return ELEM_IF;
73      }
74  
75      /**
76       * Get the executable actions contained in this &lt;if&gt;.
77       *
78       * @return Returns the actions.
79       */
80      public final List<Action> getActions() {
81          return actions;
82      }
83  
84      /**
85       * Add an Action to the list of executable actions contained in
86       * this &lt;if&gt;.
87       *
88       * @param action The action to add.
89       */
90      public final void addAction(final Action action) {
91          if (action != null) {
92              this.actions.add(action);
93          }
94      }
95  
96      /**
97       * Get the conditional expression.
98       *
99       * @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