View Javadoc
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