View Javadoc
1   package org.opentrafficsim.demo.web;
2   
3   import java.io.IOException;
4   import java.net.URL;
5   import java.util.ArrayList;
6   import java.util.LinkedHashMap;
7   import java.util.List;
8   import java.util.Map;
9   
10  import javax.servlet.ServletException;
11  import javax.servlet.http.HttpServletRequest;
12  import javax.servlet.http.HttpServletResponse;
13  
14  import org.djunits.unit.Unit;
15  import org.djunits.value.vdouble.scalar.Duration;
16  import org.djunits.value.vdouble.scalar.Time;
17  import org.djunits.value.vdouble.scalar.base.AbstractDoubleScalar;
18  import org.djunits.value.vfloat.scalar.base.AbstractFloatScalar;
19  import org.djutils.cli.Checkable;
20  import org.djutils.cli.CliUtil;
21  import org.djutils.io.URLResource;
22  import org.eclipse.jetty.server.Handler;
23  import org.eclipse.jetty.server.Request;
24  import org.eclipse.jetty.server.Server;
25  import org.eclipse.jetty.server.SessionIdManager;
26  import org.eclipse.jetty.server.handler.AbstractHandler;
27  import org.eclipse.jetty.server.handler.HandlerList;
28  import org.eclipse.jetty.server.handler.ResourceHandler;
29  import org.eclipse.jetty.server.session.DefaultSessionCache;
30  import org.eclipse.jetty.server.session.DefaultSessionIdManager;
31  import org.eclipse.jetty.server.session.NullSessionDataStore;
32  import org.eclipse.jetty.server.session.SessionCache;
33  import org.eclipse.jetty.server.session.SessionDataStore;
34  import org.eclipse.jetty.server.session.SessionHandler;
35  import org.eclipse.jetty.util.resource.Resource;
36  import org.opentrafficsim.core.animation.gtu.colorer.DefaultSwitchableGTUColorer;
37  import org.opentrafficsim.core.dsol.OTSAnimator;
38  import org.opentrafficsim.core.dsol.OTSModelInterface;
39  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
40  import org.opentrafficsim.demo.CircularRoadModel;
41  import org.opentrafficsim.demo.CrossingTrafficLightsModel;
42  import org.opentrafficsim.demo.NetworksModel;
43  import org.opentrafficsim.demo.ShortMerge;
44  import org.opentrafficsim.demo.StraightModel;
45  import org.opentrafficsim.demo.conflict.BusStreetDemo;
46  import org.opentrafficsim.demo.conflict.TJunctionDemo;
47  import org.opentrafficsim.demo.conflict.TurboRoundaboutDemo;
48  import org.opentrafficsim.demo.trafficcontrol.TrafCODDemo1;
49  import org.opentrafficsim.demo.trafficcontrol.TrafCODDemo2;
50  import org.opentrafficsim.draw.factory.DefaultAnimationFactory;
51  
52  import nl.tudelft.simulation.dsol.jetty.sse.OTSWebModel;
53  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameter;
54  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterBoolean;
55  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDistContinuousSelection;
56  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDistDiscreteSelection;
57  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDouble;
58  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDoubleScalar;
59  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterFloat;
60  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterFloatScalar;
61  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterInteger;
62  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterLong;
63  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap;
64  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterSelectionList;
65  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterSelectionMap;
66  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterString;
67  import picocli.CommandLine.Command;
68  import picocli.CommandLine.Option;
69  
70  /**
71   * Federated demo server for OTS models that uses Sim0MQ messaging to start and manage the executed models. <br>
72   * <br>
73   * Copyright (c) 2003-2020 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
74   * for project information <a href="https://www.simulation.tudelft.nl/" target="_blank">www.simulation.tudelft.nl</a>. The
75   * source code and binary code of this software is proprietary information of Delft University of Technology.
76   * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
77   */
78  @Command(description = "OTSDemoServer is a web server to run the OTS demos in a browser", name = "OTSDemoServer",
79          mixinStandardHelpOptions = true, version = "1.02.02")
80  public class OTSFederatedDemoServer implements Checkable
81  {
82      /** the map of sessionIds to OTSModelInterface that handles the animation and updates for the started model. */
83      final Map<String, OTSModelInterface> sessionModelMap = new LinkedHashMap<>();
84  
85      /** the map of sessionIds to OTSWebModel that handles the animation and updates for the started model. */
86      final Map<String, OTSWebModel> sessionWebModelMap = new LinkedHashMap<>();
87  
88      /** root directory for the web server. */
89      @SuppressWarnings("checkstyle:visibilitymodifier")
90      @Option(names = {"-r", "--rootDirectory"}, description = "Root directory of the web server", defaultValue = "/home")
91      String rootDirectory;
92  
93      /** home page for the web server. */
94      @SuppressWarnings("checkstyle:visibilitymodifier")
95      @Option(names = {"-h", "--homePage"}, description = "Home page for the web server", defaultValue = "superdemo.html")
96      String homePage;
97  
98      /** internet port for the web server. */
99      @SuppressWarnings("checkstyle:visibilitymodifier")
100     @Option(names = {"-p", "--port"}, description = "Internet port to use", defaultValue = "8080")
101     int port;
102 
103     /**
104      * Run a SuperDemo OTS Web server.
105      * @param args String[]; arguments for demo server, e.g., port=8080
106      * @throws Exception on Jetty error
107      */
108     public static void main(final String[] args) throws Exception
109     {
110         OTSFederatedDemoServerServer.html#OTSFederatedDemoServer">OTSFederatedDemoServer webApp = new OTSFederatedDemoServer();
111         CliUtil.execute(webApp, args);
112         webApp.init();
113     }
114 
115     /** {@inheritDoc} */
116     @Override
117     public void check() throws Exception
118     {
119         if (this.port < 1 || this.port > 65535)
120         {
121             throw new Exception("Port number should be between 1 and 65535");
122         }
123     }
124 
125     /** Init the server. */
126     private void init()
127     {
128         new ServerThread().start();
129     }
130 
131     /** Handle in separate thread to avoid 'lock' of the main application. */
132     class ServerThread extends Thread
133     {
134         @Override
135         public void run()
136         {
137             Server server = new Server();
138             ResourceHandler resourceHandler = new MyResourceHandler();
139 
140             // root folder; to work in Eclipse, as an external jar, and in an embedded jar
141             URL homeFolder = URLResource.getResource(OTSFederatedDemoServer.this.rootDirectory);
142             String webRoot = homeFolder.toExternalForm();
143             System.out.println("webRoot is " + webRoot);
144 
145             resourceHandler.setDirectoriesListed(true);
146             resourceHandler.setWelcomeFiles(new String[] {OTSFederatedDemoServer.this.homePage});
147             resourceHandler.setResourceBase(webRoot);
148 
149             SessionIdManager idManager = new DefaultSessionIdManager(server);
150             server.setSessionIdManager(idManager);
151 
152             SessionHandler sessionHandler = new SessionHandler();
153             SessionCache sessionCache = new DefaultSessionCache(sessionHandler);
154             SessionDataStore sessionDataStore = new NullSessionDataStore();
155             sessionCache.setSessionDataStore(sessionDataStore);
156             sessionHandler.setSessionCache(sessionCache);
157 
158             HandlerList handlers = new HandlerList();
159             handlers.setHandlers(new Handler[] {resourceHandler, sessionHandler, new XHRHandler(OTSFederatedDemoServer.this)});
160             server.setHandler(handlers);
161 
162             try
163             {
164                 server.start();
165                 server.join();
166             }
167             catch (Exception exception)
168             {
169                 exception.printStackTrace();
170             }
171         }
172     }
173 
174     /** */
175     class MyResourceHandler extends ResourceHandler
176     {
177 
178         /** {@inheritDoc} */
179         @Override
180         public Resource getResource(final String path)
181         {
182             System.out.println(path);
183             return super.getResource(path);
184         }
185 
186         /** {@inheritDoc} */
187         @Override
188         @SuppressWarnings("checkstyle:usebraces")
189         public void handle(final String target, final Request baseRequest, final HttpServletRequest request,
190                 final HttpServletResponse response) throws IOException, ServletException
191         {
192             /*-
193             System.out.println("target      = " + target);
194             System.out.println("baseRequest = " + baseRequest);
195             System.out.println("request     = " + request);
196             System.out.println("request.param " + request.getParameterMap());
197             System.out.println();
198              */
199 
200             if (target.startsWith("/parameters.html"))
201             {
202                 String modelId = request.getParameterMap().get("model")[0];
203                 String sessionId = request.getParameterMap().get("sessionId")[0];
204                 if (!OTSFederatedDemoServer.this.sessionModelMap.containsKey(sessionId))
205                 {
206                     System.out.println("parameters: " + modelId);
207                     OTSAnimator simulator = new OTSAnimator("OTSFederatedDemoServer");
208                     simulator.setAnimation(false);
209                     OTSModelInterface model = null;
210 
211                     if (modelId.toLowerCase().contains("circularroad"))
212                         model = new CircularRoadModel(simulator);
213                     else if (modelId.toLowerCase().contains("straight"))
214                         model = new StraightModel(simulator);
215                     else if (modelId.toLowerCase().contains("shortmerge"))
216                         model = new ShortMerge.ShortMergeModel(simulator);
217                     else if (modelId.toLowerCase().contains("networksdemo"))
218                         model = new NetworksModel(simulator);
219                     else if (modelId.toLowerCase().contains("crossingtrafficlights"))
220                         model = new CrossingTrafficLightsModel(simulator);
221                     else if (modelId.toLowerCase().contains("trafcoddemosimple"))
222                     {
223                         URL url = URLResource.getResource("/TrafCODDemo1/TrafCODDemo1.xml");
224                         String xml = TrafCODDemo2.readStringFromURL(url);
225                         model = new TrafCODDemo1.TrafCODModel(simulator, "TrafCODDemo1", "TrafCODDemo1", xml);
226                     }
227                     else if (modelId.toLowerCase().contains("trafcoddemocomplex"))
228                     {
229                         URL url = URLResource.getResource("/TrafCODDemo2/TrafCODDemo2.xml");
230                         String xml = TrafCODDemo2.readStringFromURL(url);
231                         model = new TrafCODDemo2.TrafCODModel(simulator, "TrafCODDemo2", "TrafCODDemo2", xml);
232                     }
233                     else if (modelId.toLowerCase().contains("tjunction"))
234                         model = new TJunctionDemo.TJunctionModel(simulator);
235                     else if (modelId.toLowerCase().contains("busstreet"))
236                         model = new BusStreetDemo.BusStreetModel(simulator);
237                     else if (modelId.toLowerCase().contains("turboroundabout"))
238                         model = new TurboRoundaboutDemo.TurboRoundaboutModel(simulator);
239 
240                     if (model != null)
241                         OTSFederatedDemoServer.this.sessionModelMap.put(sessionId, model);
242                     else
243                         System.err.println("Could not find model " + modelId);
244                 }
245             }
246 
247             if (target.startsWith("/model.html"))
248             {
249                 String modelId = request.getParameterMap().get("model")[0];
250                 String sessionId = request.getParameterMap().get("sessionId")[0];
251                 if (OTSFederatedDemoServer.this.sessionModelMap.containsKey(sessionId)
252                         && !OTSFederatedDemoServer.this.sessionWebModelMap.containsKey(sessionId))
253                 {
254                     System.out.println("startModel: " + modelId);
255                     OTSModelInterface model = OTSFederatedDemoServer.this.sessionModelMap.get(sessionId);
256                     OTSSimulatorInterface simulator = model.getSimulator();
257                     try
258                     {
259                         simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(3600.0), model);
260                         OTSWebModel webModel = new OTSWebModel(model.getShortName(), simulator);
261                         OTSFederatedDemoServer.this.sessionWebModelMap.put(sessionId, webModel);
262                         DefaultAnimationFactory.animateNetwork(model.getNetwork(), simulator,
263                                 new DefaultSwitchableGTUColorer());
264                     }
265                     catch (Exception exception)
266                     {
267                         exception.printStackTrace();
268                     }
269                 }
270             }
271 
272             // handle whatever needs to be done...
273             super.handle(target, baseRequest, request, response);
274         }
275     }
276 
277     /**
278      * Answer handles the events from the web-based user interface for a demo. <br>
279      * <br>
280      * Copyright (c) 2003-2020 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved.
281      * See for project information <a href="https://www.simulation.tudelft.nl/" target="_blank">www.simulation.tudelft.nl</a>.
282      * The source code and binary code of this software is proprietary information of Delft University of Technology.
283      * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
284      */
285     public static class XHRHandler extends AbstractHandler
286     {
287         /** web server for callback of actions. */
288         private final OTSFederatedDemoServer webServer;
289 
290         /**
291          * Create the handler for Servlet requests.
292          * @param webServer DSOLWebServer; web server for callback of actions
293          */
294         public XHRHandler(final OTSFederatedDemoServer webServer)
295         {
296             this.webServer = webServer;
297         }
298 
299         /** {@inheritDoc} */
300         @Override
301         public void handle(final String target, final Request baseRequest, final HttpServletRequest request,
302                 final HttpServletResponse response) throws IOException, ServletException
303         {
304             if (request.getParameterMap().containsKey("sessionId"))
305             {
306                 String sessionId = request.getParameterMap().get("sessionId")[0];
307                 if (this.webServer.sessionWebModelMap.containsKey(sessionId))
308                 {
309                     this.webServer.sessionWebModelMap.get(sessionId).handle(target, baseRequest, request, response);
310                 }
311                 else if (this.webServer.sessionModelMap.containsKey(sessionId))
312                 {
313                     OTSModelInterface model = this.webServer.sessionModelMap.get(sessionId);
314                     String answer = "<message>ok</message>";
315 
316                     if (request.getParameter("message") != null)
317                     {
318                         String message = request.getParameter("message");
319                         String[] parts = message.split("\\|");
320                         String command = parts[0];
321 
322                         switch (command)
323                         {
324                             case "getTitle":
325                             {
326                                 answer = "<title>" + model.getShortName() + "</title>";
327                                 break;
328                             }
329 
330                             case "getParameterMap":
331                             {
332                                 answer = makeParameterMap(model);
333                                 break;
334                             }
335 
336                             case "setParameters":
337                             {
338                                 answer = setParameters(model, message);
339                                 break;
340                             }
341 
342                             default:
343                             {
344                                 System.err.println("Got unknown message from client: " + command);
345                                 answer = "<message>" + request.getParameter("message") + "</message>";
346                                 break;
347                             }
348                         }
349                     }
350 
351                     response.setContentType("text/xml");
352                     response.setHeader("Cache-Control", "no-cache");
353                     response.setContentLength(answer.length());
354                     response.setStatus(HttpServletResponse.SC_OK);
355                     response.getWriter().write(answer);
356                     response.flushBuffer();
357                     baseRequest.setHandled(true);
358                 }
359             }
360         }
361 
362         /**
363          * Make the parameter set that can be interpreted by the parameters.html page.
364          * @param model the model with parameters
365          * @return an XML string with the parameters
366          */
367         private String makeParameterMap(final OTSModelInterface model)
368         {
369             StringBuffer answer = new StringBuffer();
370             answer.append("<parameters>\n");
371             InputParameterMap inputParameterMap = model.getInputParameterMap();
372             for (InputParameter<?, ?> tab : inputParameterMap.getSortedSet())
373             {
374                 if (!(tab instanceof InputParameterMap))
375                 {
376                     System.err.println("Input parameter " + tab.getShortName() + " cannot be displayed in a tab");
377                 }
378                 else
379                 {
380                     answer.append("<tab>" + tab.getDescription() + "</tab>\n");
381                     InputParameterMap tabbedMap = (InputParameterMap) tab;
382                     for (InputParameter<?, ?> parameter : tabbedMap.getSortedSet())
383                     {
384                         addParameterField(answer, parameter);
385                     }
386                 }
387             }
388             answer.append("</parameters>\n");
389             return answer.toString();
390         }
391 
392         /**
393          * Add the right type of field for this parameter to the string buffer.
394          * @param answer StringBuffer; the buffer to add the XML-info for the parameter
395          * @param parameter InputParameter&lt;?,?&gt;; the input parameter to display
396          */
397         public void addParameterField(final StringBuffer answer, final InputParameter<?, ?> parameter)
398         {
399             if (parameter instanceof InputParameterDouble)
400             {
401                 InputParameterDouble pd = (InputParameterDouble) parameter;
402                 answer.append("<double key='" + pd.getExtendedKey() + "' name='" + pd.getShortName() + "' description='"
403                         + pd.getDescription() + "'>" + pd.getValue() + "</double>\n");
404             }
405             else if (parameter instanceof InputParameterFloat)
406             {
407                 InputParameterFloat pf = (InputParameterFloat) parameter;
408                 answer.append("<float key='" + pf.getExtendedKey() + "' name='" + pf.getShortName() + "' description='"
409                         + pf.getDescription() + "'>" + pf.getValue() + "</float>\n");
410             }
411             else if (parameter instanceof InputParameterBoolean)
412             {
413                 InputParameterBoolean pb = (InputParameterBoolean) parameter;
414                 answer.append("<boolean key='" + pb.getExtendedKey() + "' name='" + pb.getShortName() + "' description='"
415                         + pb.getDescription() + "'>" + pb.getValue() + "</boolean>\n");
416             }
417             else if (parameter instanceof InputParameterLong)
418             {
419                 InputParameterLong pl = (InputParameterLong) parameter;
420                 answer.append("<long key='" + pl.getExtendedKey() + "' name='" + pl.getShortName() + "' description='"
421                         + pl.getDescription() + "'>" + pl.getValue() + "</long>\n");
422             }
423             else if (parameter instanceof InputParameterInteger)
424             {
425                 InputParameterInteger pi = (InputParameterInteger) parameter;
426                 answer.append("<integer key='" + pi.getExtendedKey() + "' name='" + pi.getShortName() + "' description='"
427                         + pi.getDescription() + "'>" + pi.getValue() + "</integer>\n");
428             }
429             else if (parameter instanceof InputParameterString)
430             {
431                 InputParameterString ps = (InputParameterString) parameter;
432                 answer.append("<string key='" + ps.getExtendedKey() + "' name='" + ps.getShortName() + "' description='"
433                         + ps.getDescription() + "'>" + ps.getValue() + "</string>\n");
434             }
435             else if (parameter instanceof InputParameterDoubleScalar)
436             {
437                 InputParameterDoubleScalar<?, ?> pds = (InputParameterDoubleScalar<?, ?>) parameter;
438                 String val = getValueInUnit(pds);
439                 List<String> units = getUnits(pds);
440                 answer.append("<doubleScalar key='" + pds.getExtendedKey() + "' name='" + pds.getShortName() + "' description='"
441                         + pds.getDescription() + "'><value>" + val + "</value>\n");
442                 for (String unit : units)
443                 {
444                     Unit<?> unitValue = pds.getUnitParameter().getOptions().get(unit);
445                     if (unitValue.equals(pds.getUnitParameter().getValue()))
446                         answer.append("<unit chosen='true'>" + unit + "</unit>\n");
447                     else
448                         answer.append("<unit chosen='false'>" + unit + "</unit>\n");
449                 }
450                 answer.append("</doubleScalar>\n");
451             }
452             else if (parameter instanceof InputParameterFloatScalar)
453             {
454                 InputParameterFloatScalar<?, ?> pds = (InputParameterFloatScalar<?, ?>) parameter;
455                 String val = getValueInUnit(pds);
456                 List<String> units = getUnits(pds);
457                 answer.append("<floatScalar key='" + pds.getExtendedKey() + "' name='" + pds.getShortName() + "' description='"
458                         + pds.getDescription() + "'><value>" + val + "</value>\n");
459                 for (String unit : units)
460                 {
461                     Unit<?> unitValue = pds.getUnitParameter().getOptions().get(unit);
462                     if (unitValue.equals(pds.getUnitParameter().getValue()))
463                         answer.append("<unit chosen='true'>" + unit + "</unit>\n");
464                     else
465                         answer.append("<unit chosen='false'>" + unit + "</unit>\n");
466                 }
467                 answer.append("</floatScalar>\n");
468             }
469             else if (parameter instanceof InputParameterSelectionList<?>)
470             {
471                 // TODO InputParameterSelectionList
472             }
473             else if (parameter instanceof InputParameterDistDiscreteSelection)
474             {
475                 // TODO InputParameterSelectionList
476             }
477             else if (parameter instanceof InputParameterDistContinuousSelection)
478             {
479                 // TODO InputParameterDistContinuousSelection
480             }
481             else if (parameter instanceof InputParameterSelectionMap<?, ?>)
482             {
483                 // TODO InputParameterSelectionMap
484             }
485         }
486 
487         /**
488          * @param <U> the unit
489          * @param <T> the scalar type
490          * @param parameter double scalar input parameter
491          * @return default value in the unit
492          */
493         private <U extends Unit<U>,
494                 T extends AbstractDoubleScalar<U, T>> String getValueInUnit(final InputParameterDoubleScalar<U, T> parameter)
495         {
496             return "" + parameter.getDefaultTypedValue().getInUnit(parameter.getDefaultTypedValue().getDisplayUnit());
497         }
498 
499         /**
500          * @param <U> the unit
501          * @param <T> the scalar type
502          * @param parameter double scalar input parameter
503          * @return abbreviations for the units
504          */
505         private <U extends Unit<U>,
506                 T extends AbstractDoubleScalar<U, T>> List<String> getUnits(final InputParameterDoubleScalar<U, T> parameter)
507         {
508             List<String> unitList = new ArrayList<>();
509             for (String option : parameter.getUnitParameter().getOptions().keySet())
510             {
511                 unitList.add(option.toString());
512             }
513             return unitList;
514         }
515 
516         /**
517          * @param <U> the unit
518          * @param <T> the scalar type
519          * @param parameter double scalar input parameter
520          * @return default value in the unit
521          */
522         private <U extends Unit<U>,
523                 T extends AbstractFloatScalar<U, T>> String getValueInUnit(final InputParameterFloatScalar<U, T> parameter)
524         {
525             return "" + parameter.getDefaultTypedValue().getInUnit(parameter.getDefaultTypedValue().getDisplayUnit());
526         }
527 
528         /**
529          * @param <U> the unit
530          * @param <T> the scalar type
531          * @param parameter double scalar input parameter
532          * @return abbreviations for the units
533          */
534         private <U extends Unit<U>,
535                 T extends AbstractFloatScalar<U, T>> List<String> getUnits(final InputParameterFloatScalar<U, T> parameter)
536         {
537             List<String> unitList = new ArrayList<>();
538             for (String option : parameter.getUnitParameter().getOptions().keySet())
539             {
540                 unitList.add(option.toString());
541             }
542             return unitList;
543         }
544 
545         /**
546          * Make the parameter set that can be interpreted by the parameters.html page.
547          * @param model the model with parameters
548          * @param message the key-value pairs of the set parameters
549          * @return the errors if they are detected. If none, errors is set to "OK"
550          */
551         private String setParameters(final OTSModelInterface model, final String message)
552         {
553             String errors = "OK";
554             InputParameterMap inputParameters = model.getInputParameterMap();
555             String[] parts = message.split("\\|");
556             Map<String, String> unitMap = new LinkedHashMap<>();
557             for (int i = 1; i < parts.length - 3; i += 3)
558             {
559                 String id = parts[i].trim().replaceFirst("model.", "");
560                 String type = parts[i + 1].trim();
561                 String val = parts[i + 2].trim();
562                 if (type.equals("UNIT"))
563                 {
564                     unitMap.put(id, val);
565                 }
566             }
567             for (int i = 1; i < parts.length - 3; i += 3)
568             {
569                 String id = parts[i].trim().replaceFirst("model.", "");
570                 String type = parts[i + 1].trim();
571                 String val = parts[i + 2].trim();
572 
573                 try
574                 {
575                     if (type.equals("DOUBLE"))
576                     {
577                         InputParameterDouble param = (InputParameterDouble) inputParameters.get(id);
578                         param.setDoubleValue(Double.valueOf(val));
579                     }
580                     else if (type.equals("FLOAT"))
581                     {
582                         InputParameterFloat param = (InputParameterFloat) inputParameters.get(id);
583                         param.setFloatValue(Float.valueOf(val));
584                     }
585                     else if (type.equals("BOOLEAN"))
586                     {
587                         InputParameterBoolean param = (InputParameterBoolean) inputParameters.get(id);
588                         param.setBooleanValue(val.toUpperCase().startsWith("T"));
589                     }
590                     else if (type.equals("LONG"))
591                     {
592                         InputParameterLong param = (InputParameterLong) inputParameters.get(id);
593                         param.setLongValue(Long.valueOf(val));
594                     }
595                     else if (type.equals("INTEGER"))
596                     {
597                         InputParameterInteger param = (InputParameterInteger) inputParameters.get(id);
598                         param.setIntValue(Integer.valueOf(val));
599                     }
600                     else if (type.equals("STRING"))
601                     {
602                         InputParameterString param = (InputParameterString) inputParameters.get(id);
603                         param.setStringValue(val);
604                     }
605                     if (type.equals("DOUBLESCALAR"))
606                     {
607                         InputParameterDoubleScalar<?, ?> param = (InputParameterDoubleScalar<?, ?>) inputParameters.get(id);
608                         param.getDoubleParameter().setDoubleValue(Double.valueOf(val));
609                         String unitString = unitMap.get(id);
610                         if (unitString == null)
611                             System.err.println("Could not find unit for DoubleScalar parameter with id=" + id);
612                         else
613                         {
614                             Unit<?> unit = param.getUnitParameter().getOptions().get(unitString);
615                             if (unit == null)
616                                 System.err.println(
617                                         "Could not find unit " + unitString + " for DoubleScalar parameter with id=" + id);
618                             else
619                             {
620                                 param.getUnitParameter().setObjectValue(unit);
621                                 param.setCalculatedValue(); // it will retrieve the set double value and unit
622                             }
623                         }
624                     }
625                 }
626                 catch (Exception exception)
627                 {
628                     if (errors.equals("OK"))
629                         errors = "ERRORS IN INPUT VALUES:\n";
630                     errors += "Field " + id + ": " + exception.getMessage() + "\n";
631                 }
632             }
633             return errors;
634         }
635 
636     }
637 
638 }