    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