001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *
019: */
020: package org.apache.mina.example.tapedeck;
021:
022: import static org.apache.mina.statemachine.event.IoHandlerEvents.*;
023:
024: import org.apache.mina.common.IoFutureListener;
025: import org.apache.mina.common.IoSession;
026: import org.apache.mina.statemachine.StateControl;
027: import org.apache.mina.statemachine.annotation.IoHandlerTransition;
028: import org.apache.mina.statemachine.annotation.IoHandlerTransitions;
029: import org.apache.mina.statemachine.annotation.State;
030: import org.apache.mina.statemachine.context.AbstractStateContext;
031: import org.apache.mina.statemachine.context.StateContext;
032: import org.apache.mina.statemachine.event.Event;
033:
034: /**
035: * The actual state machine implementation for the tape deck server.
036: *
037: * @author The Apache MINA Project (dev@mina.apache.org)
038: * @version $Rev: 592122 $, $Date: 2007-11-05 12:10:32 -0700 (Mon, 05 Nov 2007) $
039: */
040: public class TapeDeckServer {
041: @State
042: public static final String ROOT = "Root";
043: @State(ROOT)
044: public static final String EMPTY = "Empty";
045: @State(ROOT)
046: public static final String LOADED = "Loaded";
047: @State(ROOT)
048: public static final String PLAYING = "Playing";
049: @State(ROOT)
050: public static final String PAUSED = "Paused";
051:
052: private final String[] tapes = { "The Knife - Silent Shout",
053: "Kings of convenience - Riot on an empty street" };
054:
055: static class TapeDeckContext extends AbstractStateContext {
056: public String tapeName;
057: }
058:
059: @IoHandlerTransition(on=SESSION_OPENED,in=EMPTY)
060: public void connect(IoSession session) {
061: session.write("+ Greetings from your tape deck!");
062: }
063:
064: @IoHandlerTransition(on=MESSAGE_RECEIVED,in=EMPTY,next=LOADED)
065: public void loadTape(TapeDeckContext context, IoSession session,
066: LoadCommand cmd) {
067: if (cmd.getTapeNumber() < 1
068: || cmd.getTapeNumber() > tapes.length) {
069: session.write("- Unknown tape number: "
070: + cmd.getTapeNumber());
071: StateControl.breakAndGotoNext(EMPTY);
072: } else {
073: context.tapeName = tapes[cmd.getTapeNumber() - 1];
074: session.write("+ \"" + context.tapeName + "\" loaded");
075: }
076: }
077:
078: @IoHandlerTransitions({@IoHandlerTransition(on=MESSAGE_RECEIVED,in=LOADED,next=PLAYING),@IoHandlerTransition(on=MESSAGE_RECEIVED,in=PAUSED,next=PLAYING)})
079: public void playTape(TapeDeckContext context, IoSession session,
080: PlayCommand cmd) {
081: session.write("+ Playing \"" + context.tapeName + "\"");
082: }
083:
084: @IoHandlerTransition(on=MESSAGE_RECEIVED,in=PLAYING,next=PAUSED)
085: public void pauseTape(TapeDeckContext context, IoSession session,
086: PauseCommand cmd) {
087: session.write("+ \"" + context.tapeName + "\" paused");
088: }
089:
090: @IoHandlerTransition(on=MESSAGE_RECEIVED,in=PLAYING,next=LOADED)
091: public void stopTape(TapeDeckContext context, IoSession session,
092: StopCommand cmd) {
093: session.write("+ \"" + context.tapeName + "\" stopped");
094: }
095:
096: @IoHandlerTransition(on=MESSAGE_RECEIVED,in=LOADED,next=EMPTY)
097: public void ejectTape(TapeDeckContext context, IoSession session,
098: EjectCommand cmd) {
099: session.write("+ \"" + context.tapeName + "\" ejected");
100: context.tapeName = null;
101: }
102:
103: @IoHandlerTransition(on=MESSAGE_RECEIVED,in=ROOT)
104: public void listTapes(IoSession session, ListCommand cmd) {
105: StringBuilder response = new StringBuilder("+ (");
106: for (int i = 0; i < tapes.length; i++) {
107: response.append(i + 1).append(": ");
108: response.append('"').append(tapes[i]).append('"');
109: if (i < tapes.length - 1) {
110: response.append(", ");
111: }
112: }
113: response.append(')');
114: session.write(response);
115: }
116:
117: @IoHandlerTransition(on=MESSAGE_RECEIVED,in=ROOT)
118: public void info(TapeDeckContext context, IoSession session,
119: InfoCommand cmd) {
120: String state = context.getCurrentState().getId().toLowerCase();
121: if (context.tapeName == null) {
122: session.write("+ Tape deck is " + state + "");
123: } else {
124: session.write("+ Tape deck is " + state
125: + ". Current tape: \"" + context.tapeName + "\"");
126: }
127: }
128:
129: @IoHandlerTransition(on=MESSAGE_RECEIVED,in=ROOT)
130: public void quit(TapeDeckContext context, IoSession session,
131: QuitCommand cmd) {
132: session.write("+ Bye! Please come back!").addListener(
133: IoFutureListener.CLOSE);
134: }
135:
136: @IoHandlerTransition(on=MESSAGE_RECEIVED,in=ROOT,weight=10)
137: public void error(Event event, StateContext context,
138: IoSession session, Command cmd) {
139: session.write("- Cannot " + cmd.getName() + " while "
140: + context.getCurrentState().getId().toLowerCase());
141: }
142:
143: @IoHandlerTransition(on=EXCEPTION_CAUGHT,in=ROOT)
144: public void commandSyntaxError(IoSession session,
145: CommandSyntaxException e) {
146: session.write("- " + e.getMessage());
147: }
148:
149: @IoHandlerTransition(on=EXCEPTION_CAUGHT,in=ROOT,weight=10)
150: public void exceptionCaught(IoSession session, Exception e) {
151: e.printStackTrace();
152: session.close();
153: }
154:
155: @IoHandlerTransition(in=ROOT,weight=100)
156: public void unhandledEvent() {
157: }
158:
159: }
|