1   /*
2    * Copyright 2006 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.scxml.env;
17  
18  import java.util.Set;
19  import java.util.Timer;
20  import java.util.TimerTask;
21  
22  import org.apache.commons.scxml.env.AbstractStateMachine;
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() {
53          super(StopWatch.class.getClassLoader().
54              getResource("org/apache/commons/scxml/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                  public void run() {
70                      increment();
71                  }
72              }, 100, 100);
73          }
74      }
75  
76      public void paused() {
77          split = true;
78      }
79  
80      public void stopped() {
81          timer.cancel();
82          timer = null;
83      }
84  
85      public String getDisplay() {
86          String padhr = dhr > 9 ? EMPTY : ZERO;
87          String padmin = dmin > 9 ? EMPTY : ZERO;
88          String padsec = dsec > 9 ? EMPTY : ZERO;
89          return new StringBuffer().append(padhr).append(dhr).append(DELIM).
90              append(padmin).append(dmin).append(DELIM).append(padsec).
91              append(dsec).append(DOT).append(dfract).toString();
92      }
93  
94      // used by the demonstration (see StopWatchDisplay usecase)
95      public String getCurrentState() {
96          Set states = getEngine().getCurrentStatus().getStates();
97          return ((org.apache.commons.scxml.model.State) states.iterator().
98              next()).getId();
99      }
100 
101     private void increment() {
102         if (fract < 9) {
103             fract++;
104         } else {
105             fract = 0;
106             if (sec < 59) {
107                 sec++;
108             } else {
109                 sec = 0;
110                 if (min < 59) {
111                     min++;
112                 } else {
113                     min = 0;
114                     if (hr < 99) {
115                         hr++;
116                     } else {
117                         hr = 0; //wrap
118                     }
119                 }
120             }
121         }
122         if (!split) {
123             dhr = hr;
124             dmin = min;
125             dsec = sec;
126             dfract = fract;
127         }
128     }
129 
130 }
131