1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.scxml2.env;
18
19 import java.util.Timer;
20 import java.util.TimerTask;
21
22 import org.apache.commons.scxml2.model.ModelException;
23
24 /**
25 * A SCXML document driven stop watch.
26 *
27 * Using SCXML makes the StopWatch class simplistic; you are neither
28 * managing the stopwatch "lifecycle" nor coding any "transitions",
29 * that information is pulled in straight from the behavioral model
30 * of the stop watch, which is encapsulated in the SCXML document
31 * the constructor points to (which in turn may be generated straight
32 * from the UML model).
33 */
34 public class StopWatch extends AbstractStateMachine {
35
36 /** The events for the stop watch. */
37 public static final String EVENT_START = "watch.start",
38 EVENT_STOP = "watch.stop", EVENT_SPLIT = "watch.split",
39 EVENT_UNSPLIT = "watch.unsplit", EVENT_RESET = "watch.reset";
40
41 /** The fragments of the elapsed time. */
42 private int hr, min, sec, fract;
43 /** The fragments of the display time. */
44 private int dhr, dmin, dsec, dfract;
45 /** The stopwatch "split" (display freeze). */
46 private boolean split;
47 /** The Timer to keep time. */
48 private Timer timer;
49 /** The display decorations. */
50 private static final String DELIM = ":", DOT = ".", EMPTY = "", ZERO = "0";
51
52 public StopWatch() throws ModelException {
53 super(StopWatch.class.getClassLoader().
54 getResource("org/apache/commons/scxml2/env/stopwatch.xml"));
55 }
56
57 // Each method below is the activity corresponding to a state in the
58 // SCXML document (see class constructor for pointer to the document).
59 public void reset() {
60 hr = min = sec = fract = dhr = dmin = dsec = dfract = 0;
61 split = false;
62 }
63
64 public void running() {
65 split = false;
66 if (timer == null) {
67 timer = new Timer(true);
68 timer.scheduleAtFixedRate(new TimerTask() {
69 @Override
70 public void run() {
71 increment();
72 }
73 }, 100, 100);
74 }
75 }
76
77 public void paused() {
78 split = true;
79 }
80
81 public void stopped() {
82 timer.cancel();
83 timer = null;
84 }
85
86 public String getDisplay() {
87 String padhr = dhr > 9 ? EMPTY : ZERO;
88 String padmin = dmin > 9 ? EMPTY : ZERO;
89 String padsec = dsec > 9 ? EMPTY : ZERO;
90 return new StringBuffer().append(padhr).append(dhr).append(DELIM).
91 append(padmin).append(dmin).append(DELIM).append(padsec).
92 append(dsec).append(DOT).append(dfract).toString();
93 }
94
95 // used by the demonstration (see StopWatchDisplay usecase)
96 public String getCurrentState() {
97 return getEngine().getStatus().getStates().iterator().next().getId();
98 }
99
100 private void increment() {
101 if (fract < 9) {
102 fract++;
103 } else {
104 fract = 0;
105 if (sec < 59) {
106 sec++;
107 } else {
108 sec = 0;
109 if (min < 59) {
110 min++;
111 } else {
112 min = 0;
113 if (hr < 99) {
114 hr++;
115 } else {
116 hr = 0; //wrap
117 }
118 }
119 }
120 }
121 if (!split) {
122 dhr = hr;
123 dmin = min;
124 dsec = sec;
125 dfract = fract;
126 }
127 }
128
129 }
130