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.env;
018:
019: import java.util.Set;
020: import java.util.Timer;
021: import java.util.TimerTask;
022:
023: import org.apache.commons.scxml.env.AbstractStateMachine;
024:
025: /**
026: * A SCXML document driven stop watch.
027: *
028: * Using SCXML makes the StopWatch class simplistic; you are neither
029: * managing the stopwatch "lifecycle" nor coding any "transitions",
030: * that information is pulled in straight from the behavioral model
031: * of the stop watch, which is encapsulated in the SCXML document
032: * the constructor points to (which in turn may be generated straight
033: * from the UML model).
034: */
035: public class StopWatch extends AbstractStateMachine {
036:
037: /** The events for the stop watch. */
038: public static final String EVENT_START = "watch.start",
039: EVENT_STOP = "watch.stop", EVENT_SPLIT = "watch.split",
040: EVENT_UNSPLIT = "watch.unsplit",
041: EVENT_RESET = "watch.reset";
042:
043: /** The fragments of the elapsed time. */
044: private int hr, min, sec, fract;
045: /** The fragments of the display time. */
046: private int dhr, dmin, dsec, dfract;
047: /** The stopwatch "split" (display freeze). */
048: private boolean split;
049: /** The Timer to keep time. */
050: private Timer timer;
051: /** The display decorations. */
052: private static final String DELIM = ":", DOT = ".", EMPTY = "",
053: ZERO = "0";
054:
055: public StopWatch() {
056: super (StopWatch.class.getClassLoader().getResource(
057: "org/apache/commons/scxml/env/stopwatch.xml"));
058: }
059:
060: // Each method below is the activity corresponding to a state in the
061: // SCXML document (see class constructor for pointer to the document).
062: public void reset() {
063: hr = min = sec = fract = dhr = dmin = dsec = dfract = 0;
064: split = false;
065: }
066:
067: public void running() {
068: split = false;
069: if (timer == null) {
070: timer = new Timer(true);
071: timer.scheduleAtFixedRate(new TimerTask() {
072: public void run() {
073: increment();
074: }
075: }, 100, 100);
076: }
077: }
078:
079: public void paused() {
080: split = true;
081: }
082:
083: public void stopped() {
084: timer.cancel();
085: timer = null;
086: }
087:
088: public String getDisplay() {
089: String padhr = dhr > 9 ? EMPTY : ZERO;
090: String padmin = dmin > 9 ? EMPTY : ZERO;
091: String padsec = dsec > 9 ? EMPTY : ZERO;
092: return new StringBuffer().append(padhr).append(dhr).append(
093: DELIM).append(padmin).append(dmin).append(DELIM)
094: .append(padsec).append(dsec).append(DOT).append(dfract)
095: .toString();
096: }
097:
098: // used by the demonstration (see StopWatchDisplay usecase)
099: public String getCurrentState() {
100: Set states = getEngine().getCurrentStatus().getStates();
101: return ((org.apache.commons.scxml.model.State) states
102: .iterator().next()).getId();
103: }
104:
105: private void increment() {
106: if (fract < 9) {
107: fract++;
108: } else {
109: fract = 0;
110: if (sec < 59) {
111: sec++;
112: } else {
113: sec = 0;
114: if (min < 59) {
115: min++;
116: } else {
117: min = 0;
118: if (hr < 99) {
119: hr++;
120: } else {
121: hr = 0; //wrap
122: }
123: }
124: }
125: }
126: if (!split) {
127: dhr = hr;
128: dmin = min;
129: dsec = sec;
130: dfract = fract;
131: }
132: }
133:
134: }
|