View Javadoc

1   /*
2    * Copyright (C) 2006  Tom Gibara
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17   */
18  package com.tomgibara.pronto.control.impl;
19  
20  import java.util.HashSet;
21  
22  import com.tomgibara.pronto.control.Controller;
23  import com.tomgibara.pronto.control.EngineControlAdapter;
24  import com.tomgibara.pronto.state.StateEngine;
25  import com.tomgibara.pronto.util.Arguments;
26  
27  /**
28   * The standard implementation of the Controller interface. It aggregates a
29   * number of ControllerParts that provide its actual functionality. This means
30   * that a single instance of this class can actually provide 'multiple'
31   * functionality based on the a settings object that implements a number of
32   * different ControllerSettings interfaces.
33   *
34   * @param <S>
35   *            the type of state
36   * @param <L>
37   *            the type of label
38   * @param <P>
39   *            the type of parameter
40   *
41   * @author Tom Gibara
42   * 
43   */
44  
45  public class ControllerImpl<S, L, P> implements Controller<S, L, P> {
46  
47      // fields
48  
49      private final HashSet<ControllerPart> parts = new HashSet<ControllerPart>();
50  
51      /**
52       * Direct package-scope access is provided so that controller parts can
53       * obtain a reference to the engine they must operate over.
54       */
55  
56      final StateEngine<S, L, P> engine;
57  
58      /**
59       * Direct package-scope access is provided so that controller parts can
60       * obtain a reference to the adapter they should use.
61       */
62  
63      final CheckedAdapter<S, L, P> adapter;
64  
65      // constructors
66  
67      public ControllerImpl(final StateEngine<S, L, P> engine, final EngineControlAdapter<S, L, P> adapter) {
68          Arguments.notNull(engine, "engine");
69          Arguments.notNull(adapter, "adapter");
70  
71          this.engine = engine;
72          this.adapter = new CheckedAdapter<S, L, P>(adapter);
73      }
74  
75      // controller methods
76  
77      public EngineControlAdapter<S, L, P> getAdapter() {
78          return adapter.getAdapter();
79      }
80  
81      public StateEngine<S, L, P> getEngine() {
82          return engine;
83      }
84  
85      public void start() {
86          for (ControllerPart<S, L, P> part : parts) {
87              part.start();
88          }
89      }
90  
91      public boolean stop(final long timeout) {
92          Arguments.notNegative(timeout, "timeout");
93          boolean success = true;
94          if (timeout == 0L) {
95              for (ControllerPart<S, L, P> part : parts) {
96                  success = success && part.stop(0L);
97              }
98          } else {
99              final long start = System.currentTimeMillis();
100             for (ControllerPart<S, L, P> part : parts) {
101                 final long now = System.currentTimeMillis();
102                 success = success && part.stop(timeout - (now - start));
103             }
104         }
105         return success;
106     }
107 
108     // package methods
109 
110     void addPart(final ControllerPart<S, L, P> part) {
111         if (part.getController() != this) throw new IllegalArgumentException("Part not made for this controller.");
112         parts.add(part);
113     }
114 
115     boolean isEmpty() {
116         return parts.isEmpty();
117     }
118 
119 }