    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.util.LinkedHashMap;
    020    import java.util.Map;
    021
    022    /**
    023     * The class in this SCXML object model that corresponds to the
    024     * <state> SCXML element.
    025     *
    026     */
    027    public class State extends TransitionTarget {
    028
    029        /**
    030         * Serial version UID.
    031         */
    032        private static final long serialVersionUID = 2L;
    033
    034        /**
    035         * The Map containing immediate children of this State, keyed by
    036         * their IDs. Incompatible with the parallel or invoke property.
    037         */
    038        private Map children;
    039
    040        /**
    041         * The Parallel child, which defines a set of parallel substates.
    042         * May occur 0 or 1 times. Incompatible with the state or invoke property.
    043         */
    044        private Parallel parallel;
    045
    046        /**
    047         * The Invoke child, which defines an external process that should
    048         * be invoked, immediately after the onentry executable content,
    049         * and the transitions become candidates after the invoked
    050         * process has completed its execution.
    051         * May occur 0 or 1 times. Incompatible with the state or parallel
    052         * property.
    053         */
    054        private Invoke invoke;
    055
    056        /**
    057         * Boolean property indicating whether this is a final state or not.
    058         * Default value is false . Final states may not have substates or
    059         * outgoing transitions.
    060         */
    061        private boolean isFinal;
    062
    063        /**
    064         * A child which identifies initial state for state machines that
    065         * have substates.
    066         */
    067        private Initial initial;
    068
    069        /**
    070         * Applies to composite states only. If one of its final children is
    071         * active, its parent is marked done. This property is reset upon
    072         * re-entry.
    073         *
    074         * @deprecated Will be removed in v1.0
    075         */
    076        private boolean done = false;
    077
    078        /**
    079         * Constructor.
    080         */
    081        public State() {
    082            this.children = new LinkedHashMap();
    083        }
    084
    085        /**
    086         * Is this state a "final" state.
    087         *
    088         * @return boolean Returns the isFinal.
    089         * @deprecated Use {@link #isFinal()} instead
    090         */
    091        public final boolean getIsFinal() {
    092            return isFinal;
    093        }
    094
    095        /**
    096         * Set whether this is a "final" state.
    097         *
    098         * @param isFinal
    099         *            The isFinal to set.
    100         * @deprecated Use {@link #setFinal(boolean)} instead
    101         */
    102        public final void setIsFinal(final boolean isFinal) {
    103            this.isFinal = isFinal;
    104        }
    105
    106        /**
    107         * Is this state a "final" state.
    108         *
    109         * @return boolean Returns the isFinal.
    110         *
    111         * @since 0.7
    112         */
    113        public final boolean isFinal() {
    114            return isFinal;
    115        }
    116
    117        /**
    118         * Set whether this is a "final" state.
    119         *
    120         * @param isFinal
    121         *            The isFinal to set.
    122         *
    123         * @since 0.7
    124         */
    125        public final void setFinal(final boolean isFinal) {
    126            this.isFinal = isFinal;
    127        }
    128
    129        /**
    130         * Get the Parallel child (may be null).
    131         *
    132         * @return Parallel Returns the parallel.
    133         *
    134         * @deprecated <parallel> no longer needs an enclosing
    135         *             <state> element.
    136         */
    137        public final Parallel getParallel() {
    138            return parallel;
    139        }
    140
    141        /**
    142         * Set the Parallel child.
    143         *
    144         * @param parallel
    145         *            The parallel to set.
    146         *
    147         * @deprecated <parallel> no longer needs an enclosing
    148         *             <state> element.
    149         */
    150        public final void setParallel(final Parallel parallel) {
    151            this.parallel = parallel;
    152        }
    153
    154        /**
    155         * Get the Invoke child (may be null).
    156         *
    157         * @return Invoke Returns the invoke.
    158         */
    159        public final Invoke getInvoke() {
    160            return invoke;
    161        }
    162
    163        /**
    164         * Set the Invoke child.
    165         *
    166         * @param invoke
    167         *            The invoke to set.
    168         */
    169        public final void setInvoke(final Invoke invoke) {
    170            this.invoke = invoke;
    171        }
    172
    173        /**
    174         * Get the initial state.
    175         *
    176         * @return Initial Returns the initial state.
    177         */
    178        public final Initial getInitial() {
    179            return initial;
    180        }
    181
    182        /**
    183         * Set the initial state.
    184         *
    185         * @param target
    186         *            The target to set.
    187         */
    188        public final void setInitial(final Initial target) {
    189            this.initial = target;
    190            target.setParent(this);
    191        }
    192
    193        /**
    194         * Get the initial state's ID.
    195         *
    196         * @return The initial state's string ID.
    197         */
    198        public final String getFirst() {
    199            if (initial != null) {
    200                return initial.getTransition().getNext();
    201            }
    202            return null;
    203        }
    204
    205        /**
    206         * Set the initial state by its ID string.
    207         *
    208         * @param target
    209         *            The initial target's ID to set.
    210         */
    211        public final void setFirst(final String target) {
    212            Transition t = new Transition();
    213            t.setNext(target);
    214            Initial ini = new Initial();
    215            ini.setTransition(t);
    216            ini.setParent(this);
    217            this.initial = ini;
    218        }
    219
    220        /**
    221         * Get the map of child states (may be empty).
    222         *
    223         * @return Map Returns the children.
    224         */
    225        public final Map getChildren() {
    226            return children;
    227        }
    228
    229        /**
    230         * Add a child state.
    231         *
    232         * @param state
    233         *            a child state
    234         *
    235         * @deprecated Use {@link #addChild(TransitionTarget)} instead.
    236         */
    237        public final void addChild(final State state) {
    238            this.children.put(state.getId(), state);
    239            state.setParent(this);
    240        }
    241
    242        /**
    243         * Add a child transition target.
    244         *
    245         * @param tt
    246         *            a child transition target
    247         *
    248         * @since 0.7
    249         */
    250        public final void addChild(final TransitionTarget tt) {
    251            this.children.put(tt.getId(), tt);
    252            tt.setParent(this);
    253        }
    254
    255        /**
    256         * Check whether this is a simple (leaf) state (UML terminology).
    257         *
    258         * @return true if this is a simple state, otherwise false
    259         */
    260        public final boolean isSimple() {
    261            if (parallel == null && children.isEmpty()) {
    262                return true;
    263            }
    264            return false;
    265        }
    266
    267        /**
    268         * Check whether this is a composite state (UML terminology).
    269         *
    270         * @return true if this is a composite state, otherwise false
    271         */
    272        public final boolean isComposite() {
    273            if (parallel == null && children.isEmpty()) {
    274                return false;
    275            }
    276            return true;
    277        }
    278
    279        /**
    280         * Checks whether it is a region state (directly nested to parallel - UML
    281         * terminology).
    282         *
    283         * @return true if this is a region state, otherwise false
    284         * @see Parallel
    285         */
    286        public final boolean isRegion() {
    287            if (getParent() instanceof Parallel) {
    288                return true;
    289            }
    290            return false;
    291        }
    292
    293        /**
    294         * Checks whether it is a orthogonal state, that is, it owns a parallel
    295         * (UML terminology).
    296         *
    297         * @return true if this is a orthogonal state, otherwise false
    298         * @deprecated <parallel> now represents an orthogonal state, rather
    299         *             than denoting that the enclosing state is orthogonal, as
    300         *             it did in previous SCXML WDs.
    301         */
    302        public final boolean isOrthogonal() {
    303            if (parallel != null) {
    304                return true;
    305            }
    306            return false;
    307        }
    308
    309        /**
    310         * In case this is a parallel state, check if one its final states
    311         * is active.
    312         *
    313         * @return Returns the done.
    314         * @deprecated Will be removed in v1.0, in favor of
    315         *             <code>SCInstance#isDone(TransitionTarget)</code>
    316         */
    317        public final boolean isDone() {
    318            return done;
    319        }
    320
    321        /**
    322         * Update the done property, which is set if this is a parallel state,
    323         * and one its final states is active.
    324         *
    325         * @param done The done to set.
    326         * @deprecated Will be removed in v1.0, in favor of
    327         *             <code>SCInstance#setDone(TransitionTarget)</code>
    328         */
    329        public final void setDone(final boolean done) {
    330            this.done = done;
    331        }
    332    }
    333