1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package com.tomgibara.pronto.control.impl;
19
20 import java.util.HashSet;
21 import java.util.logging.Logger;
22
23 import com.tomgibara.pronto.control.ControlFactory;
24 import com.tomgibara.pronto.control.Controller;
25 import com.tomgibara.pronto.control.ControllerSettings;
26 import com.tomgibara.pronto.control.EngineControlAdapter;
27 import com.tomgibara.pronto.control.FileControllerSettings;
28 import com.tomgibara.pronto.control.ProntoControlException;
29 import com.tomgibara.pronto.control.SignalControllerSettings;
30 import com.tomgibara.pronto.control.StdinControllerSettings;
31 import com.tomgibara.pronto.state.StateEngine;
32 import com.tomgibara.pronto.util.Arguments;
33
34 /**
35 * The standard implementation of the ControlFactory interface.
36 *
37 * @author Tom Gibara
38 *
39 */
40
41 public class ControlFactoryImpl extends ControlFactory {
42
43
44
45 /**
46 * The log for exceptions and other log worthy events. This logger is
47 * intended to be shared by all the classes in this package.
48 */
49
50 static final Logger LOGGER = Logger.getLogger(ControlFactoryImpl.class.getPackage().getName());
51
52
53
54 /**
55 * Maintains a set of part factories that are consulted when a control
56 * interface (or its implementation) is supplied to the factory.
57 */
58
59 private final HashSet<PartFactory> factories = new HashSet<PartFactory>();
60
61
62
63 public ControlFactoryImpl() {
64
65 factories.add(new PartFactory() {
66 public boolean isSupported(final Class<? extends ControllerSettings> clss) {
67 return FileControllerSettings.class.isAssignableFrom(clss);
68 }
69
70 public <S, L, P> ControllerPart<S, L, P> newPart(final ControllerImpl<S, L, P> controller,
71 final ControllerSettings settings) throws ProntoControlException {
72 return new FileControllerPart<S, L, P>(controller, (FileControllerSettings) settings);
73 }
74 });
75
76
77 factories.add(new PartFactory() {
78 public boolean isSupported(final Class<? extends ControllerSettings> clss) {
79 return StdinControllerSettings.class.isAssignableFrom(clss);
80 }
81
82 public <S, L, P> ControllerPart<S, L, P> newPart(final ControllerImpl<S, L, P> controller,
83 final ControllerSettings settings) throws ProntoControlException {
84 return new StdinControllerPart<S, L, P>(controller, (StdinControllerSettings) settings);
85 }
86 });
87
88
89 factories.add(new PartFactory() {
90 public boolean isSupported(final Class<? extends ControllerSettings> clss) {
91 return SignalControllerSettings.class.isAssignableFrom(clss);
92 }
93
94 public <S, L, P> ControllerPart<S, L, P> newPart(final ControllerImpl<S, L, P> controller,
95 final ControllerSettings settings) throws ProntoControlException {
96 return new SignalControllerPart<S, L, P>(controller, (SignalControllerSettings) settings);
97 }
98 });
99
100
101 }
102
103 @Override
104 public boolean isSettingsIfaceSupported(final Class<? extends ControllerSettings> iface) {
105 Arguments.notNull(iface, "iface");
106 if (!iface.isInterface()) throw new IllegalArgumentException("iface must be interface");
107 for (PartFactory factory : factories) {
108 if (factory.isSupported(iface)) return true;
109 }
110 return false;
111 }
112
113 @Override
114 public <S, L, P> Controller<S, L, P> newController(final ControllerSettings settings,
115 final StateEngine<S, L, P> engine, final EngineControlAdapter<S, L, P> adapter)
116 throws ProntoControlException {
117 Arguments.notNull(settings, "settings");
118 Arguments.notNull(engine, "engine");
119 Arguments.notNull(adapter, "adapter");
120 ControllerImpl<S, L, P> controller = new ControllerImpl<S, L, P>(engine, adapter);
121
122 for (PartFactory factory : factories) {
123 if (!factory.isSupported(settings.getClass())) continue;
124 controller.addPart(factory.newPart(controller, settings));
125 }
126
127 if (controller.isEmpty()) throw new IllegalArgumentException(String.format("Unsupported interface: %s",
128 settings.getClass()));
129 return controller;
130 }
131
132
133
134 /**
135 * Part factories create ControllerPart implementations that are combined by
136 * this factory to form a Controller.
137 */
138
139 private interface PartFactory {
140
141 /**
142 * Whether the part factory recognizes the interface.
143 *
144 * @param iface
145 * an interface that has been supplied to the factory
146 * @return true if this factory can create a controller from an instance
147 * of the supplied interface
148 */
149
150 boolean isSupported(Class<? extends ControllerSettings> iface);
151
152 /**
153 * Creates a new controller part that draws its settings from a supplied
154 * settings object. The controller for which the part is being created
155 * is supplied to provide access to the state engine and adapter that
156 * the part is expected to operate over.
157 *
158 * @param <S>
159 * the state type
160 * @param <L>
161 * the label type
162 * @param <P>
163 * the parameter type
164 * @param controller
165 * the controller to which the part will be added
166 * @param settings
167 * an implementation of a settings interface
168 * @return a new instance of a controller part
169 * @throws ProntoControlException
170 */
171
172 <S, L, P> ControllerPart<S, L, P> newPart(ControllerImpl<S, L, P> controller, ControllerSettings settings)
173 throws ProntoControlException;
174
175 }
176
177 }