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     */
017    package org.apache.commons.scxml.model;
018    
019    import java.io.Serializable;
020    import java.util.Collection;
021    import java.util.Map;
022    
023    import org.apache.commons.logging.Log;
024    import org.apache.commons.scxml.ErrorReporter;
025    import org.apache.commons.scxml.EventDispatcher;
026    import org.apache.commons.scxml.SCInstance;
027    import org.apache.commons.scxml.SCXMLExpressionException;
028    
029    /**
030     * An abstract base class for executable elements in SCXML,
031     * such as <assign>, <log> etc.
032     *
033     */
034    public abstract class Action implements NamespacePrefixesHolder,
035            Serializable {
036    
037        /**
038         * Link to its parent or container.
039         */
040        private Executable parent;
041    
042        /**
043         * The current XML namespaces in the SCXML document for this action node,
044         * preserved for deferred XPath evaluation.
045         */
046        private Map namespaces;
047    
048        /**
049         * Current document namespaces are saved under this key in the parent
050         * state's context.
051         */
052        private static final String NAMESPACES_KEY = "_ALL_NAMESPACES";
053    
054        /**
055         * Constructor.
056         */
057        public Action() {
058            super();
059            this.parent = null;
060            this.namespaces = null;
061        }
062    
063        /**
064         * Get the Executable parent.
065         *
066         * @return Returns the parent.
067         */
068        public final Executable getParent() {
069            return parent;
070        }
071    
072        /**
073         * Set the Executable parent.
074         *
075         * @param parent The parent to set.
076         */
077        public final void setParent(final Executable parent) {
078            this.parent = parent;
079        }
080    
081        /**
082         * Get the XML namespaces at this action node in the SCXML document.
083         *
084         * @return Returns the map of namespaces.
085         */
086        public final Map getNamespaces() {
087            return namespaces;
088        }
089    
090        /**
091         * Set the XML namespaces at this action node in the SCXML document.
092         *
093         * @param namespaces The document namespaces.
094         */
095        public final void setNamespaces(final Map namespaces) {
096            this.namespaces = namespaces;
097        }
098    
099        /**
100         * Return the parent state.
101         *
102         * @return The parent State
103         * @throws ModelException For an unknown TransitionTarget subclass
104         *
105         * @deprecated Use {@link #getParentTransitionTarget()} instead.
106         */
107        public final State getParentState() throws ModelException {
108            TransitionTarget tt = parent.getParent();
109            if (tt instanceof State) {
110                State st = (State) tt;
111                return st;
112            } else if (tt instanceof Parallel || tt instanceof History) {
113                State st = (State) tt.getParent();
114                return st;
115            } else {
116                throw new ModelException("Unknown TransitionTarget subclass:"
117                        + tt.getClass().getName());
118            }
119        }
120    
121        /**
122         * Return the {@link TransitionTarget} whose {@link Context} this action
123         * executes in.
124         *
125         * @return The parent {@link TransitionTarget}
126         * @throws ModelException For an unknown TransitionTarget subclass
127         *
128         * @since 0.9
129         */
130        public final TransitionTarget getParentTransitionTarget()
131        throws ModelException {
132            TransitionTarget tt = parent.getParent();
133            if (tt instanceof State || tt instanceof Parallel) {
134                return tt;
135            } else if (tt instanceof History || tt instanceof Initial) {
136                return tt.getParent();
137            } else {
138                throw new ModelException("Unknown TransitionTarget subclass:"
139                        + tt.getClass().getName());
140            }
141        }
142    
143        /**
144         * Execute this action instance.
145         *
146         * @param evtDispatcher The EventDispatcher for this execution instance
147         * @param errRep        The ErrorReporter to broadcast any errors
148         *                      during execution.
149         * @param scInstance    The state machine execution instance information.
150         * @param appLog        The application Log.
151         * @param derivedEvents The collection to which any internal events
152         *                      arising from the execution of this action
153         *                      must be added.
154         *
155         * @throws ModelException If the execution causes the model to enter
156         *                        a non-deterministic state.
157         * @throws SCXMLExpressionException If the execution involves trying
158         *                        to evaluate an expression which is malformed.
159         */
160        public abstract void execute(final EventDispatcher evtDispatcher,
161            final ErrorReporter errRep, final SCInstance scInstance,
162            final Log appLog, final Collection derivedEvents)
163        throws ModelException, SCXMLExpressionException;
164    
165        /**
166         * Return the key under which the current document namespaces are saved
167         * in the parent state's context.
168         *
169         * @return The namespaces key
170         */
171        protected static String getNamespacesKey() {
172            return NAMESPACES_KEY;
173        }
174    
175    }
176