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;
018
019import java.io.Serializable;
020import java.util.Collections;
021import java.util.HashSet;
022import java.util.Set;
023
024import org.apache.commons.scxml2.model.EnterableState;
025
026/**
027 * The current active states of a state machine
028 */
029public class StateConfiguration implements Serializable {
030    /**
031     * Serial version UID.
032     */
033    private static final long serialVersionUID = 1L;
034
035    /**
036     * The states that are currently active.
037     */
038    private final Set<EnterableState> activeStates = new HashSet<EnterableState>();
039    private final Set<EnterableState> activeStatesSet = Collections.unmodifiableSet(activeStates);
040
041    /**
042     * The atomic states that are currently active.
043     */
044    private final Set<EnterableState> atomicStates = new HashSet<EnterableState>();
045    private final Set<EnterableState> atomicStatesSet = Collections.unmodifiableSet(atomicStates);
046
047    /**
048     * Get the active states
049     *
050     * @return active states including simple states and their
051     *         complex ancestors up to the root.
052     */
053    public Set<EnterableState> getActiveStates() {
054        return  activeStatesSet;
055    }
056
057    /**
058     * Get the current atomic states (leaf only).
059     *
060     * @return Returns the atomic states - simple (leaf) states only.
061     */
062    public Set<EnterableState> getStates() {
063        return  atomicStatesSet;
064    }
065
066    /**
067     * Enter an active state
068     * If the state is atomic also record it add it to the current states
069     * @param state state to enter
070     */
071    public void enterState(final EnterableState state) {
072        if (!activeStates.add(state)) {
073            throw new IllegalStateException("State "+state.getId()+" already added.");
074        }
075        if (state.isAtomicState()) {
076            if (!atomicStates.add(state)) {
077                throw new IllegalStateException("Atomic state "+state.getId()+" already added.");
078            }
079        }
080    }
081
082    /**
083     * Exit an active state
084     * If the state is atomic also remove it from current states
085     * @param state state to exit
086     */
087    public void exitState(final EnterableState state) {
088        if (!activeStates.remove(state)) {
089            throw new IllegalStateException("State "+state.getId()+" not active.");
090        }
091        atomicStates.remove(state);
092    }
093
094    /**
095     * Clear the state configuration
096     */
097    public void clear() {
098        activeStates.clear();
099        atomicStates.clear();
100    }
101}