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.Map; 020import java.util.StringTokenizer; 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.semantics.ErrorConstants; 027 028/** 029 * A <code>NamelistHolder</code> represents an element in the SCXML 030 * document that may have a namelist attribute to 031 * produce payload for events or external communication. 032 */ 033public abstract class NamelistHolder extends ParamsContainer { 034 035 /** 036 * The namelist. 037 */ 038 private String namelist; 039 040 /** 041 * Get the namelist. 042 * 043 * @return String Returns the namelist. 044 */ 045 public final String getNamelist() { 046 return namelist; 047 } 048 049 /** 050 * Set the namelist. 051 * 052 * @param namelist The namelist to set. 053 */ 054 public final void setNamelist(final String namelist) { 055 this.namelist = namelist; 056 } 057 058 /** 059 * Adds data to the payload data map based on the namelist which names are location expressions 060 * (typically data ids or for example XPath variables). The names and the values they 'point' at 061 * are added to the payload data map. 062 * @param exctx The ActionExecutionContext 063 * @param payload the payload data map to be updated 064 * @throws ModelException if this action has not an EnterableState as parent 065 * @throws SCXMLExpressionException if a malformed or invalid expression is evaluated 066 * @see PayloadProvider#addToPayload(String, Object, java.util.Map) 067 */ 068 protected void addNamelistDataToPayload(ActionExecutionContext exctx, Map<String, Object> payload) 069 throws ModelException, SCXMLExpressionException { 070 if (namelist != null) { 071 EnterableState parentState = getParentEnterableState(); 072 Context ctx = exctx.getContext(parentState); 073 try { 074 ctx.setLocal(getNamespacesKey(), getNamespaces()); 075 Evaluator evaluator = exctx.getEvaluator(); 076 StringTokenizer tkn = new StringTokenizer(namelist); 077 boolean xpathEvaluator = Evaluator.XPATH_DATA_MODEL.equals(evaluator.getSupportedDatamodel()); 078 while (tkn.hasMoreTokens()) { 079 String varName = tkn.nextToken(); 080 Object varObj = evaluator.eval(ctx, varName); 081 if (varObj == null) { 082 //considered as a warning here 083 exctx.getErrorReporter().onError(ErrorConstants.UNDEFINED_VARIABLE, 084 varName + " = null", parentState); 085 } 086 if (xpathEvaluator && varName.startsWith("$")) { 087 varName = varName.substring(1); 088 } 089 addToPayload(varName, varObj, payload); 090 } 091 } 092 finally { 093 ctx.setLocal(getNamespacesKey(), null); 094 } 095 } 096 } 097}