public boolean gotoState(final String str_state, Object... cl_data) {
		// attempt to get the new state
		FSMState lcl_newState = mcla_states.get(str_state);

		if (lcl_newState == null) {
			BTLog.debug(this, "gotoState", "No state found for " + str_state);
			return false;
		}
		
		FSMState lcl_currentState = null;
		Transition lcl_t = null;
		if(currentState != null) {
			// see if there is a legal transition for it
			lcl_t = getTransitionByStates(currentState, str_state);
			if (lcl_t == null) {
				BTLog.error(this, "gotoState", "illegal transition from " + currentState + " to " + str_state);
				return false;
			}
			
			// notify the state that we are leaving
			lcl_currentState = mcla_states.get(currentState);
			lcl_currentState.getHandler().exit(lcl_currentState, lcl_newState);
		}

		// initialise the new state with the data provided
		currentState = str_state;
		lcl_newState.getStateVariables().clear();
		lcl_newState.getStateVariables().make(cl_data);
		lcl_newState.getHandler().enter(lcl_currentState, lcl_newState);
		
		// notify any listeners that the state has changed
		if(lcl_t != null) {
			List<ITransitionEventListener> lcla_evt = mcla_transitionListeners.get(lcl_t.getEventID());
			if (lcla_evt != null) {
				for (ITransitionEventListener lcl_evt : lcla_evt) {
					lcl_evt.stateChanged(lcl_t.getEventID(), lcl_currentState, lcl_newState);
				}
			}
		}

		BTLog.debug(this, "gotoState", "state transition complete for " + lcl_newState.getId());
		
		return true;
	}