1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package broadwick;
17
18 import broadwick.config.ConfigValidationErrors;
19 import broadwick.config.ConfigValidator;
20 import broadwick.config.generated.Logs;
21 import broadwick.config.generated.Models;
22 import broadwick.config.generated.Project;
23 import broadwick.data.DataReader;
24 import broadwick.data.Lookup;
25 import broadwick.model.Model;
26 import com.google.common.base.Throwables;
27 import com.google.common.util.concurrent.ThreadFactoryBuilder;
28 import java.io.File;
29 import java.io.IOException;
30 import java.io.StringReader;
31 import java.io.StringWriter;
32 import java.util.HashMap;
33 import java.util.Map;
34 import java.util.Map.Entry;
35 import java.util.concurrent.ExecutorService;
36 import java.util.concurrent.Executors;
37 import java.util.concurrent.ThreadFactory;
38 import java.util.concurrent.TimeUnit;
39 import javax.xml.bind.JAXBContext;
40 import javax.xml.bind.JAXBException;
41 import javax.xml.bind.Unmarshaller;
42 import javax.xml.parsers.DocumentBuilder;
43 import javax.xml.parsers.DocumentBuilderFactory;
44 import javax.xml.parsers.ParserConfigurationException;
45 import javax.xml.transform.OutputKeys;
46 import javax.xml.transform.Transformer;
47 import javax.xml.transform.TransformerException;
48 import javax.xml.transform.TransformerFactory;
49 import javax.xml.transform.dom.DOMSource;
50 import javax.xml.transform.stream.StreamResult;
51 import org.apache.commons.lang3.time.StopWatch;
52 import org.slf4j.Logger;
53 import org.w3c.dom.Document;
54 import org.w3c.dom.NamedNodeMap;
55 import org.w3c.dom.NodeList;
56 import org.xml.sax.InputSource;
57 import org.xml.sax.SAXException;
58
59
60
61
62 public final class Broadwick {
63
64
65
66
67
68
69 public Broadwick(final String[] args) {
70
71 final LoggingFacade logFacade = new LoggingFacade();
72 log = logFacade.getRootLogger();
73 try {
74 final CliOptions cli = new CliOptions(args);
75 readConfigFile(logFacade, cli.getConfigurationFileName());
76 } catch (BroadwickException ex) {
77 log.error("{}\nSomething went wrong starting project. See the error messages.", ex.getLocalizedMessage());
78 log.trace(Throwables.getStackTraceAsString(ex));
79 }
80 }
81
82
83
84
85
86
87
88 private void readConfigFile(final LoggingFacade logFacade, final String configFile) {
89 if (!configFile.isEmpty()) {
90 final File cfg = new File(configFile);
91 if (!cfg.exists()) {
92 throw new BroadwickException("Configuration file [" + configFile + "] does not exist.");
93 }
94 try {
95
96 final JAXBContext jaxbContext = JAXBContext.newInstance(Constants.GENERATED_CONFIG_CLASSES_DIR);
97 final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
98 project = (Project) unmarshaller.unmarshal(cfg);
99
100
101 final StringWriter writer = new StringWriter();
102 jaxbContext.createMarshaller().marshal(project, writer);
103 configXml = writer.toString();
104
105
106 final ConfigValidator validator = new ConfigValidator(project);
107 final ConfigValidationErrors validationErrors = validator.validate();
108
109
110
111 final Logs.File file = project.getLogs().getFile();
112 if (file != null) {
113 logFacade.addFileLogger(file.getName(), file.getLevel(), file.getPattern(), file.isOverwrite());
114 }
115 final Logs.Console console = project.getLogs().getConsole();
116 if (console != null) {
117 logFacade.addConsoleLogger(console.getLevel(), console.getPattern());
118 }
119
120
121 if (validationErrors.getNumErrors() > 0) {
122 log.error("Invalid configuration file.\n{}Correct any errors before continuing.", validationErrors.getValidationErrors());
123 project = validator.getValidatedProject();
124 }
125
126 } catch (JAXBException ex) {
127 log.error("Could not read configuration file. {}", ex.toString());
128 log.trace(com.google.common.base.Throwables.getStackTraceAsString(ex));
129 }
130 } else {
131 throw new BroadwickException("No configuration file specified");
132 }
133 }
134
135
136
137
138 @SuppressWarnings("squid:S1147")
139 public void run() {
140 if (project != null) {
141 final StopWatch sw = new StopWatch();
142 sw.start();
143
144
145 log.info("Running broadwick {}", BroadwickVersion.getVersionAndTimeStamp());
146
147 try (DataReader dr = new DataReader(project.getData())) {
148 final Map<String, Model> registeredModels = registerModels(project, dr.getLookup());
149 log.info("Running broadwick for the following models {}", registeredModels.keySet());
150
151
152
153 final int poolSize = registeredModels.size();
154 if (poolSize > 0) {
155 final ThreadFactory threadFactory = new ThreadFactoryBuilder()
156 .setNameFormat("BroadwickModels-%d")
157 .setDaemon(true)
158 .build();
159 final ExecutorService es = Executors.newFixedThreadPool(poolSize, threadFactory);
160
161
162 for (final Entry<String, Model> entry : registeredModels.entrySet()) {
163 es.submit(new Runnable() {
164 @Override
165 public void run() {
166 final String modelName = entry.getKey();
167 final Model model = entry.getValue();
168 try {
169 log.info("Running {} [{}]", modelName, model.getClass().getCanonicalName());
170 model.init();
171 model.run();
172 model.finalise();
173 } catch (Exception ex) {
174 log.error("Error running model {}. see stack trace from details.", modelName);
175 log.error("{}", Throwables.getStackTraceAsString(ex));
176 }
177 }
178 });
179 }
180 es.shutdown();
181 while (!es.isTerminated()) {
182 es.awaitTermination(10, TimeUnit.SECONDS);
183 }
184
185
186 }
187 } catch (Exception ex) {
188 log.error("{}", ex.getLocalizedMessage());
189 log.error("{}", Throwables.getStackTraceAsString(ex));
190 log.error("Something went wrong. See previous messages for details.");
191 }
192
193 log.info("Simulation complete. {}", sw.toString());
194
195
196 Runtime.getRuntime().exit(0);
197 }
198 }
199
200
201
202
203
204
205
206
207
208 private Map<String, Model> registerModels(final Project project, final Lookup lookup) {
209 final Map<String, Model> registeredModels = new HashMap<>();
210 try {
211
212 for (Models.Model model : project.getModels().getModel()) {
213
214 final Model newInstance = Model.class.cast(Class.forName(model.getClassname()).newInstance());
215 newInstance.setModelConfiguration(getModelsConfiguration(model.getId(), getAllModelConfigurations()));
216 newInstance.setModelDataLookup(lookup);
217 newInstance.setModelParameters(model.getParameter());
218 if (model.getPriors() != null) {
219 newInstance.setModelPriors(model.getPriors().getGaussianPriorAndUniformPrior());
220 }
221 registeredModels.put(model.getId(), newInstance);
222 }
223 } catch (ParserConfigurationException | SAXException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException ex) {
224 log.error("Could not create model ; {}", ex.getLocalizedMessage());
225 registeredModels.clear();
226 }
227
228 return registeredModels;
229 }
230
231
232
233
234
235
236
237
238
239 private NodeList getAllModelConfigurations() throws ParserConfigurationException, SAXException, IOException {
240 final DocumentBuilderFactory xmlFactory = DocumentBuilderFactory.newInstance();
241 final DocumentBuilder docBuilder = xmlFactory.newDocumentBuilder();
242 final Document xmlDoc = docBuilder.parse(new InputSource(new StringReader(configXml)));
243 return xmlDoc.getElementsByTagName("model");
244 }
245
246
247
248
249
250
251
252
253 private String getModelsConfiguration(final String id, final NodeList models) {
254 try {
255 for (int i = 0; i < models.getLength(); i++) {
256 final NamedNodeMap attributes = models.item(i).getAttributes();
257 final String nodeId = attributes.getNamedItem("id").getNodeValue();
258
259 if (id.equals(nodeId)) {
260 final TransformerFactory transFactory = TransformerFactory.newInstance();
261 final Transformer transformer = transFactory.newTransformer();
262 final StringWriter buffer = new StringWriter();
263 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
264 transformer.transform(new DOMSource(models.item(i)),
265 new StreamResult(buffer));
266 return buffer.toString();
267 }
268 }
269 } catch (TransformerException ex) {
270 log.error("Could not get the configuration for the model [{}]. {}", id, ex.getLocalizedMessage());
271 }
272 return "";
273 }
274
275
276
277
278
279
280 public static void main(final String[] args) {
281
282 final Broadwick broadwick = new Broadwick(args);
283 broadwick.run();
284 }
285 private Project project;
286 private Logger log;
287 private String configXml;
288 }