    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