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.Map;
20  import java.util.StringTokenizer;
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.semantics.ErrorConstants;
27  
28  /**
29   * A <code>NamelistHolder</code> represents an element in the SCXML
30   * document that may have a namelist attribute to
31   * produce payload for events or external communication.
32   */
33  public abstract class NamelistHolder extends ParamsContainer {
34  
35      /**
36       * The namelist.
37       */
38      private String namelist;
39  
40      /**
41       * Get the namelist.
42       *
43       * @return String Returns the namelist.
44       */
45      public final String getNamelist() {
46          return namelist;
47      }
48  
49      /**
50       * Set the namelist.
51       *
52       * @param namelist The namelist to set.
53       */
54      public final void setNamelist(final String namelist) {
55          this.namelist = namelist;
56      }
57  
58      /**
59       * Adds data to the payload data map based on the namelist which names are location expressions
60       * (typically data ids or for example XPath variables). The names and the values they 'point' at
61       * are added to the payload data map.
62       * @param exctx The ActionExecutionContext
63       * @param payload the payload data map to be updated
64       * @throws ModelException if this action has not an EnterableState as parent
65       * @throws SCXMLExpressionException if a malformed or invalid expression is evaluated
66       * @see PayloadProvider#addToPayload(String, Object, java.util.Map)
67       */
68      protected void addNamelistDataToPayload(ActionExecutionContext exctx, Map<String, Object> payload)
69              throws ModelException, SCXMLExpressionException {
70          if (namelist != null) {
71              EnterableState parentState = getParentEnterableState();
72              Context ctx = exctx.getContext(parentState);
73              try {
74                  ctx.setLocal(getNamespacesKey(), getNamespaces());
75                  Evaluator evaluator = exctx.getEvaluator();
76                  StringTokenizer tkn = new StringTokenizer(namelist);
77                  boolean xpathEvaluator = Evaluator.XPATH_DATA_MODEL.equals(evaluator.getSupportedDatamodel());
78                  while (tkn.hasMoreTokens()) {
79                      String varName = tkn.nextToken();
80                      Object varObj = evaluator.eval(ctx, varName);
81                      if (varObj == null) {
82                          //considered as a warning here
83                          exctx.getErrorReporter().onError(ErrorConstants.UNDEFINED_VARIABLE,
84                                  varName + " = null", parentState);
85                      }
86                      if (xpathEvaluator && varName.startsWith("$")) {
87                          varName = varName.substring(1);
88                      }
89                      addToPayload(varName, varObj, payload);
90                  }
91              }
92              finally {
93                  ctx.setLocal(getNamespacesKey(), null);
94              }
95          }
96      }
97  }