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.scxml.env;
18  
19  import java.util.Set;
20  import java.util.Timer;
21  import java.util.TimerTask;
22  
23  import org.apache.commons.scxml.env.AbstractStateMachine;
24  
25  /***
26   * A SCXML document driven stop watch.
27   *
28   * Using SCXML makes the StopWatch class simplistic; you are neither
29   * managing the stopwatch "lifecycle" nor coding any "transitions",
30   * that information is pulled in straight from the behavioral model
31   * of the stop watch, which is encapsulated in the SCXML document
32   * the constructor points to (which in turn may be generated straight
33   * from the UML model).
34   */
35  public class StopWatch extends AbstractStateMachine {
36  
37      /*** The events for the stop watch. */
38      public static final String EVENT_START = "watch.start",
39          EVENT_STOP = "watch.stop", EVENT_SPLIT = "watch.split",
40          EVENT_UNSPLIT = "watch.unsplit", EVENT_RESET = "watch.reset";
41  
42      /*** The fragments of the elapsed time. */
43      private int hr, min, sec, fract;
44      /*** The fragments of the display time. */
45      private int dhr, dmin, dsec, dfract;
46      /*** The stopwatch "split" (display freeze). */
47      private boolean split;
48      /*** The Timer to keep time. */
49      private Timer timer;
50      /*** The display decorations. */
51      private static final String DELIM = ":", DOT = ".", EMPTY = "", ZERO = "0";
52  
53      public StopWatch() {
54          super(StopWatch.class.getClassLoader().
55              getResource("org/apache/commons/scxml/env/stopwatch.xml"));
56      }
57  
58      // Each method below is the activity corresponding to a state in the
59      // SCXML document (see class constructor for pointer to the document).
60      public void reset() {
61          hr = min = sec = fract = dhr = dmin = dsec = dfract = 0;
62          split = false;
63      }
64  
65      public void running() {
66          split = false;
67          if (timer == null) {
68              timer = new Timer(true);
69              timer.scheduleAtFixedRate(new TimerTask() {
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          Set states = getEngine().getCurrentStatus().getStates();
98          return ((org.apache.commons.scxml.model.State) states.iterator().
99              next()).getId();
100     }
101 
102     private void increment() {
103         if (fract < 9) {
104             fract++;
105         } else {
106             fract = 0;
107             if (sec < 59) {
108                 sec++;
109             } else {
110                 sec = 0;
111                 if (min < 59) {
112                     min++;
113                 } else {
114                     min = 0;
115                     if (hr < 99) {
116                         hr++;
117                     } else {
118                         hr = 0; //wrap
119                     }
120                 }
121             }
122         }
123         if (!split) {
124             dhr = hr;
125             dmin = min;
126             dsec = sec;
127             dfract = fract;
128         }
129     }
130 
131 }
132