/Source/HydroModeler/Utilities/OpenMI/sdk/Wrapper/LinkableRunEngine.cs

# · C# · 848 lines · 521 code · 111 blank · 216 comment · 48 complexity · de215007bd89dd83af46575fe3756359 MD5 · raw file

  1. #region Copyright
  2. /*
  3. * Copyright (c) 2005,2006,2007, OpenMI Association
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * * Neither the name of the OpenMI Association nor the
  14. * names of its contributors may be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY "OpenMI Association" ``AS IS'' AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL "OpenMI Association" BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  26. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #endregion
  29. using System;
  30. using System.Collections;
  31. using System.Runtime.Remoting;
  32. using OpenMI.Standard;
  33. using Oatc.OpenMI.Sdk.Backbone;
  34. using Oatc.OpenMI.Sdk.DevelopmentSupport;
  35. namespace Oatc.OpenMI.Sdk.Wrapper
  36. {
  37. /// <summary>
  38. /// The LinkableRunEngine implements the run time part of the ILinkableComponent interface.
  39. /// The remaining methods are implemented in the derived LinkableEngine class. There are
  40. /// historical reasons for splitting the functionality between the two classes.
  41. /// The LinkableRunEngine class and the LinkableEngine class could be merged,
  42. /// but for the time being these are keeps as they are in order to support backward compatibility.
  43. /// </summary>
  44. [Serializable]
  45. public abstract class LinkableRunEngine : LinkableComponent
  46. {
  47. //TODO: The elementset version number should be checked and the elementmapper
  48. //called in order to update the mapping a matrix when the version has changed
  49. /// <summary>
  50. /// List of SmartInputLinks
  51. /// </summary>
  52. protected ArrayList _smartInputLinks;
  53. /// <summary>
  54. /// List of SmartOutput Links
  55. /// </summary>
  56. protected ArrayList _smartOutputLinks;
  57. /// <summary>
  58. /// Reference to the engine. Must be assigned in the derived class
  59. /// </summary>
  60. protected IRunEngine _engineApiAccess;
  61. /// <summary>
  62. /// True if the _engineApiAccess was assigned
  63. /// </summary>
  64. protected bool _engineWasAssigned;
  65. /// <summary>
  66. /// True if the Initialize method was invoked
  67. /// </summary>
  68. protected bool _initializeWasInvoked;
  69. /// <summary>
  70. /// True if the Prepare method was invoked
  71. /// </summary>
  72. protected bool _prepareForCompotationWasInvoked;
  73. /// <summary>
  74. /// True if the component is gathering data from other LinkableComponents
  75. /// </summary>
  76. protected bool _isBusy;
  77. /// <summary>
  78. /// Arraylist of published event types
  79. /// </summary>
  80. protected ArrayList _publishedEventTypes;
  81. /// <summary>
  82. /// used when comparing time in the IsLater method (see property TimeEpsilon)
  83. /// </summary>
  84. protected double _timeEpsilon; // used when comparing time in the IsLater method (see property TimeEpsilon)
  85. /// <summary>
  86. /// Current validation string from the Validate method
  87. /// </summary>
  88. protected ArrayList _validationWarningMessages;
  89. /// <summary>
  90. /// The current validateion error message
  91. /// </summary>
  92. protected ArrayList _validationErrorMessages;
  93. /// <summary>
  94. /// Constructor method for the LinkableRunEngine class
  95. /// </summary>
  96. public LinkableRunEngine()
  97. {
  98. _engineWasAssigned = false;
  99. _initializeWasInvoked = false;
  100. _prepareForCompotationWasInvoked = false;
  101. _timeEpsilon = 0.10 * 1.0 / (3600.0 * 24.0);
  102. _publishedEventTypes = new ArrayList();
  103. _publishedEventTypes.Add(EventType.DataChanged);
  104. _publishedEventTypes.Add(EventType.Informative);
  105. _publishedEventTypes.Add(EventType.SourceAfterGetValuesCall);
  106. _publishedEventTypes.Add(EventType.SourceBeforeGetValuesReturn);
  107. _publishedEventTypes.Add(EventType.TargetAfterGetValuesReturn);
  108. _publishedEventTypes.Add(EventType.TargetBeforeGetValuesCall);
  109. _validationWarningMessages = new ArrayList();
  110. _validationErrorMessages = new ArrayList();
  111. _smartInputLinks = new ArrayList();
  112. _smartOutputLinks = new ArrayList();
  113. }
  114. /// <summary>
  115. /// Implementation of the same method in the
  116. /// OpenMI.Standard.ILinkableComponent interface
  117. /// </summary>
  118. public override ITimeStamp EarliestInputTime
  119. {
  120. get
  121. {
  122. return (_engineApiAccess.GetEarliestNeededTime());
  123. }
  124. }
  125. /// <summary>
  126. /// This _timeEpsilon variable is used when comparing the current time in the engine with
  127. /// the time specified in the parameters for the GetValue method.
  128. /// if ( requestedTime > engineTime + _timeEpsilon) then PerformTimestep()..
  129. /// The default values for _timeEpsilon is double.Epsilon = 4.94065645841247E-324
  130. /// The default value may be too small for some engines, in which case the _timeEpsilon can
  131. /// be changed the class that you have inherited from LinkableRunEngine og LinkableEngine.
  132. /// </summary>
  133. public double TimeEpsilon
  134. {
  135. get
  136. {
  137. return _timeEpsilon;
  138. }
  139. set
  140. {
  141. _timeEpsilon = value;
  142. }
  143. }
  144. /// <summary>
  145. /// Add a link to the LinkableComponent
  146. /// </summary>
  147. /// <param name="newLink">The Link</param>
  148. public override void AddLink(ILink newLink)
  149. {
  150. try
  151. {
  152. if (!_initializeWasInvoked)
  153. {
  154. throw new System.Exception("AddLink method in the SmartWrapper cannot be invoked before the Initialize method has been invoked");
  155. }
  156. if (_prepareForCompotationWasInvoked)
  157. {
  158. throw new System.Exception("AddLink method in the SmartWrapper cannot be invoked after the PrepareForComputation method has been invoked");
  159. }
  160. if(newLink.TargetComponent == this)
  161. {
  162. _smartInputLinks.Add (this.CreateInputLink(this._engineApiAccess, newLink));
  163. }
  164. else if(newLink.SourceComponent == this)
  165. {
  166. this._smartOutputLinks.Add (this.CreateOutputLink(this._engineApiAccess, newLink));
  167. }
  168. else
  169. {
  170. throw new System.Exception("SourceComponent.ID or TargetComponent.ID in Link does not match the Component ID for the component to which the Link was added");
  171. }
  172. }
  173. catch (System.Exception e)
  174. {
  175. string message = "Exception in LinkableComponent. ";
  176. message += "ComponentID: " + this.ComponentID + "\n";
  177. throw new System.Exception(message,e);
  178. }
  179. }
  180. /// <summary>
  181. /// Creates a new input link
  182. /// </summary>
  183. /// <param name="engine">The engine</param>
  184. /// <param name="link">The link</param>
  185. /// <returns>The new input link</returns>
  186. public virtual SmartInputLink CreateInputLink(IRunEngine engine, ILink link)
  187. {
  188. return new SmartInputLink (engine, link);
  189. }
  190. /// <summary>
  191. /// Creates a new output link
  192. /// </summary>
  193. /// <param name="engine">The engine</param>
  194. /// <param name="link">The link</param>
  195. /// <returns>The new output link</returns>
  196. public virtual SmartOutputLink CreateOutputLink(IRunEngine engine, ILink link)
  197. {
  198. SmartOutputLink smartOutputLink = new SmartOutputLink (engine, link);
  199. smartOutputLink.Initialize();
  200. return smartOutputLink;
  201. }
  202. /// <summary>
  203. /// Implementaion of the same method in the
  204. /// OpenMI.Standard.ILinkableComponent
  205. /// </summary>
  206. public override void Dispose()
  207. {
  208. _engineApiAccess.Dispose();
  209. }
  210. /// <summary>
  211. /// Implementation of the same method in
  212. /// OpenMI.Standard.ILInkableComponent
  213. /// </summary>
  214. /// <param name="time">Time (ITimeSpan or ITimeStamp) for which values are requested</param>
  215. /// <param name="LinkID">LinkID associated to the requested values</param>
  216. /// <returns>The values</returns>
  217. public override IValueSet GetValues(ITime time, string LinkID)
  218. {
  219. try
  220. {
  221. CheckTimeArgumentInGetvaluesMethod(time);
  222. SendSourceAfterGetValuesCallEvent(time, LinkID);
  223. IValueSet engineResult = new ScalarSet();
  224. int outputLinkIndex = -999;
  225. for (int i = 0; i < _smartOutputLinks.Count; i++)
  226. {
  227. if ( ((SmartOutputLink) _smartOutputLinks[i]).link.ID == LinkID)
  228. {
  229. outputLinkIndex = i;
  230. break;
  231. }
  232. }
  233. if (_isBusy==false)
  234. {
  235. //while(IsLater(time,_engineApiAccess.GetCurrentTime()))
  236. while(IsLater(time, ((SmartOutputLink) _smartOutputLinks[outputLinkIndex]).GetLastBufferedTime()))
  237. {
  238. _isBusy=true;
  239. //Update input links
  240. foreach(SmartInputLink smartInputLink in _smartInputLinks)
  241. {
  242. smartInputLink.UpdateInput();
  243. }
  244. _isBusy=false;
  245. //Perform Timestep
  246. if(_engineApiAccess.PerformTimeStep())
  247. {
  248. //Update buffer with engine values, Time is timestamp
  249. foreach (SmartOutputLink smartOutputLink in _smartOutputLinks)
  250. {
  251. smartOutputLink.UpdateBuffer();
  252. }
  253. SendEvent(EventType.DataChanged);
  254. }
  255. }
  256. }
  257. engineResult = ((SmartOutputLink)_smartOutputLinks[outputLinkIndex]).GetValue(time);
  258. SendEvent(EventType.SourceBeforeGetValuesReturn);
  259. return engineResult;
  260. }
  261. catch (System.Exception e)
  262. {
  263. string message = "Exception in LinkableComponent. ComponentID: ";
  264. message += this.ComponentID;
  265. throw new System.Exception(message,e);
  266. }
  267. }
  268. /// <summary>
  269. /// Description of the component
  270. /// </summary>
  271. public override string ComponentDescription
  272. {
  273. get
  274. {
  275. return _engineApiAccess.GetComponentDescription();
  276. }
  277. }
  278. /// <summary>
  279. /// ID for the component
  280. /// </summary>
  281. public override string ComponentID
  282. {
  283. get
  284. {
  285. if (_engineApiAccess != null)
  286. {
  287. return _engineApiAccess.GetComponentID();
  288. }
  289. else
  290. {
  291. return null;
  292. }
  293. }
  294. }
  295. /// <summary>
  296. /// Finish
  297. /// </summary>
  298. public override void Finish()
  299. {
  300. _engineApiAccess.Finish();
  301. }
  302. /// <summary>
  303. /// Initialize
  304. /// </summary>
  305. /// <param name="properties">Initialization parameters</param>
  306. public override void Initialize(IArgument[] properties)
  307. {
  308. System.Collections.Hashtable hashtable =new Hashtable();
  309. for(int i = 0; i < properties.Length;i++)
  310. {
  311. hashtable.Add(properties[i].Key,properties[i].Value);
  312. }
  313. SetEngineApiAccess();
  314. this._engineWasAssigned = true;
  315. _engineApiAccess.Initialize(hashtable);
  316. if (!_engineWasAssigned)
  317. {
  318. throw new System.Exception("The Initialize method in the SmartWrapper cannot be invoked before the EngineApiAccess is assigned" );
  319. }
  320. _initializeWasInvoked = true;
  321. }
  322. /// <summary>
  323. /// Prepare. This method will be invoked after end of configuration and before the first GetValues call
  324. /// </summary>
  325. public override void Prepare()
  326. {
  327. try
  328. {
  329. if (!_engineWasAssigned)
  330. {
  331. throw new System.Exception("PrepareForComputation method in SmartWrapper cannot be invoked before the EngineApiAccess has been assigned");
  332. }
  333. if (!_initializeWasInvoked)
  334. {
  335. throw new System.Exception("PrepareForComputation method in SmartWrapper cannot be invoked before the Initialize method has been invoked");
  336. }
  337. Validate();
  338. if (_validationErrorMessages.Count > 0)
  339. {
  340. string errorMessage = "";
  341. foreach (string str in _validationErrorMessages)
  342. {
  343. errorMessage += "Error: " + str + ". ";
  344. }
  345. throw new Exception(errorMessage);
  346. }
  347. foreach (SmartOutputLink smartOutputLink in _smartOutputLinks)
  348. {
  349. smartOutputLink.UpdateBuffer();
  350. }
  351. _prepareForCompotationWasInvoked = true;
  352. }
  353. catch (System.Exception e)
  354. {
  355. string message = "Exception in LinkableComponent. ";
  356. message += "ComponentID: " + this.ComponentID + "\n";
  357. throw new System.Exception(message,e);
  358. }
  359. }
  360. /// <summary>
  361. /// Remove a link
  362. /// </summary>
  363. /// <param name="LinkID">Link ID for the link to be removed</param>
  364. public override void RemoveLink(string LinkID)
  365. {
  366. try
  367. {
  368. if (!_initializeWasInvoked)
  369. {
  370. throw new Exception("Illegal invocation of RemoveLink method before invocation of Initialize method");
  371. }
  372. if (_prepareForCompotationWasInvoked)
  373. {
  374. throw new Exception("Illegal invocation of RemoveLink method after invocation of Prepare method");
  375. }
  376. int index = -999;
  377. for (int i = 0; i < _smartInputLinks.Count; i++)
  378. {
  379. if (((SmartInputLink)_smartInputLinks[i]).link.ID == LinkID)
  380. {
  381. index = i;
  382. break;
  383. }
  384. }
  385. if (index != -999)
  386. {
  387. _smartInputLinks.RemoveAt(index);
  388. }
  389. else
  390. {
  391. for (int i = 0; i < _smartOutputLinks.Count; i++)
  392. {
  393. if(((SmartOutputLink) _smartOutputLinks[i]).link.ID == LinkID)
  394. {
  395. index = i;
  396. break;
  397. }
  398. }
  399. _smartOutputLinks.RemoveAt(index);
  400. }
  401. if (index == -999)
  402. {
  403. throw new Exception("Failed to find link.ID in internal link lists in method RemoveLink()");
  404. }
  405. }
  406. catch (System.Exception e)
  407. {
  408. string message = "Exception in LinkableComponent. ";
  409. message += "ComponentID: " + this.ComponentID + "\n";
  410. throw new System.Exception(message,e);
  411. }
  412. }
  413. /// <summary>
  414. /// Returns an array of input ILink which contains links already added to this component.
  415. /// </summary>
  416. /// <returns>Returns an array of ILink which contains links already added to this component</returns>
  417. public override ILink[] GetAcceptingLinks()
  418. {
  419. ArrayList links = new ArrayList();
  420. foreach (SmartInputLink smartLink in _smartInputLinks)
  421. {
  422. links.Add (smartLink.link);
  423. }
  424. return (ILink[]) links.ToArray(typeof(ILink));
  425. }
  426. /// <summary>
  427. /// Returns an array of output ILink which contains links already added to this component.
  428. /// </summary>
  429. /// <returns>Returns an array of output ILink which contains links already added to this component.</returns>
  430. public override ILink[] GetProvidingLinks()
  431. {
  432. ArrayList links = new ArrayList();
  433. foreach (SmartOutputLink smartLink in _smartOutputLinks)
  434. {
  435. links.Add (smartLink.link);
  436. }
  437. return (ILink[]) links.ToArray(typeof(ILink));
  438. }
  439. /// <summary>
  440. /// Get the reference to the engine
  441. /// </summary>
  442. public IRunEngine EngineApiAccess
  443. {
  444. get
  445. {
  446. return _engineApiAccess;
  447. }
  448. }
  449. /// <summary>
  450. /// Set reference to the engine
  451. /// </summary>
  452. protected abstract void SetEngineApiAccess();
  453. /// <summary>
  454. /// Keep Curren state
  455. /// </summary>
  456. /// <returns>ID for the state keept</returns>
  457. public virtual string KeepCurrentState()
  458. {
  459. if (_engineApiAccess is IManageState)
  460. {
  461. string stateID;
  462. stateID = ((IManageState) _engineApiAccess).KeepCurrentState();
  463. foreach (SmartOutputLink smartOutputLink in _smartOutputLinks)
  464. {
  465. smartOutputLink.KeepCurrentBufferState(stateID);
  466. }
  467. return stateID;
  468. }
  469. else
  470. {
  471. throw new Exception("KeepCurrentState was called but the engine does not implement IManageState");
  472. }
  473. }
  474. /// <summary>
  475. /// Restore a state
  476. /// </summary>
  477. /// <param name="stateID">ID for the state to restore</param>
  478. public virtual void RestoreState(string stateID)
  479. {
  480. if (_engineApiAccess is IManageState)
  481. {
  482. ((IManageState) _engineApiAccess).RestoreState(stateID);
  483. foreach (SmartOutputLink smartOutputLink in _smartOutputLinks)
  484. {
  485. smartOutputLink.RestoreBufferState(stateID);
  486. }
  487. }
  488. else
  489. {
  490. throw new Exception("RestoreState was called but the engine does not implement IManageState");
  491. }
  492. }
  493. /// <summary>
  494. /// Clear a state
  495. /// </summary>
  496. /// <param name="stateID">ID for the state to clear</param>
  497. public virtual void ClearState(string stateID)
  498. {
  499. if (_engineApiAccess is IManageState)
  500. {
  501. ((IManageState) _engineApiAccess).ClearState(stateID);
  502. foreach (SmartOutputLink smartOutputLink in _smartOutputLinks)
  503. {
  504. smartOutputLink.ClearBufferState(stateID);
  505. }
  506. }
  507. else
  508. {
  509. throw new Exception("ClearState was called but the engine does not implement IManageState");
  510. }
  511. }
  512. /// <summary>
  513. /// Get the published event types.
  514. /// </summary>
  515. /// <param name="providedEventTypeIndex">index for the requested event type</param>
  516. /// <returns>the requested event type</returns>
  517. public override EventType GetPublishedEventType(int providedEventTypeIndex)
  518. {
  519. return (EventType) _publishedEventTypes[providedEventTypeIndex];
  520. }
  521. /// <summary>
  522. /// Get the number of published event types
  523. /// </summary>
  524. /// <returns>Number of published event types</returns>
  525. public override int GetPublishedEventTypeCount()
  526. {
  527. return _publishedEventTypes.Count;
  528. }
  529. /// <summary>
  530. /// Convert a ITime object to a ITimeStamp.
  531. /// </summary>
  532. /// <param name="time">The ITime object to convert</param>
  533. /// <returns>The converted time</returns>
  534. public static Oatc.OpenMI.Sdk.Backbone.TimeStamp TimeToTimeStamp(ITime time)
  535. {
  536. Oatc.OpenMI.Sdk.Backbone.TimeStamp t;
  537. if (time is ITimeStamp)
  538. {
  539. t = new Oatc.OpenMI.Sdk.Backbone.TimeStamp(((ITimeStamp) time).ModifiedJulianDay);
  540. }
  541. else
  542. {
  543. t = new Oatc.OpenMI.Sdk.Backbone.TimeStamp(((ITimeSpan) time).End.ModifiedJulianDay);
  544. }
  545. return t;
  546. }
  547. /// <summary>
  548. /// Will compare two times. If the first argument t1, is later than the second argument t2
  549. /// the method will return true. Otherwise false will be returned. t1 and t2 can be of types
  550. /// ITimeSpan or ITimeStamp.
  551. /// </summary>
  552. /// <param name="t1">First time</param>
  553. /// <param name="t2">Second time</param>
  554. /// <returns>isLater</returns>
  555. protected bool IsLater(ITime t1, ITime t2)
  556. {
  557. double mt1, mt2;
  558. bool isLater = false;
  559. mt1 = TimeToTimeStamp(t1).ModifiedJulianDay;
  560. mt2 = TimeToTimeStamp(t2).ModifiedJulianDay;
  561. if (mt1 > mt2 + _timeEpsilon)
  562. {
  563. isLater = true;
  564. }
  565. else
  566. {
  567. isLater = false;
  568. }
  569. return isLater;
  570. }
  571. /// <summary>
  572. /// Converts a ITime object to a formatted string
  573. /// </summary>
  574. /// <param name="time">The time to convert</param>
  575. /// <returns>The formatted string</returns>
  576. public static string ITimeToString(ITime time)
  577. {
  578. string timeString;
  579. if (time is ITimeStamp)
  580. {
  581. timeString = (CalendarConverter.ModifiedJulian2Gregorian(((ITimeStamp) time).ModifiedJulianDay)).ToString();
  582. }
  583. else if (time is ITimeSpan)
  584. {
  585. timeString = "[" + (CalendarConverter.ModifiedJulian2Gregorian(((ITimeSpan) time).Start.ModifiedJulianDay)).ToString() + ", " + (CalendarConverter.ModifiedJulian2Gregorian(((ITimeSpan) time).End.ModifiedJulianDay)).ToString() + "]";
  586. }
  587. else
  588. {
  589. throw new System.Exception("Illigal type used for time, must be OpenMI.Standard.ITimeStamp or OpenMI.Standard.TimeSpan");
  590. }
  591. return timeString;
  592. }
  593. /// <summary>
  594. /// Model descscription
  595. /// </summary>
  596. public override abstract string ModelDescription
  597. {
  598. get;
  599. }
  600. /// <summary>
  601. /// Model ID
  602. /// </summary>
  603. public override abstract string ModelID
  604. {
  605. get;
  606. }
  607. /// <summary>
  608. /// Time Horizon
  609. /// </summary>
  610. public override abstract ITimeSpan TimeHorizon
  611. {
  612. get;
  613. }
  614. /// <summary>
  615. /// Number of input exchange items
  616. /// </summary>
  617. public override abstract int InputExchangeItemCount
  618. {
  619. get;
  620. }
  621. /// <summary>
  622. /// number of output exchange items
  623. /// </summary>
  624. public override abstract int OutputExchangeItemCount
  625. {
  626. get;
  627. }
  628. /// <summary>
  629. /// get an input exchange item
  630. /// </summary>
  631. /// <param name="index">index number for the requested input exchange item</param>
  632. /// <returns>the requested input exchange item</returns>
  633. public override abstract IInputExchangeItem GetInputExchangeItem(int index);
  634. /// <summary>
  635. /// get an output exchange item.
  636. /// </summary>
  637. /// <param name="index">index number for the requested exchange item</param>
  638. /// <returns>the requested exchange item</returns>
  639. public override abstract IOutputExchangeItem GetOutputExchangeItem(int index);
  640. private ArrayList GetAllLinks()
  641. {
  642. ArrayList links = new ArrayList();
  643. foreach (SmartInputLink inputLink in _smartInputLinks)
  644. {
  645. links.Add(inputLink.link);
  646. }
  647. foreach (SmartOutputLink outputLink in _smartOutputLinks)
  648. {
  649. links.Add(outputLink.link);
  650. }
  651. return links;
  652. }
  653. /// <summary>
  654. /// Validate the component
  655. /// </summary>
  656. /// <returns>Empty string if no warnings were issued, or a description if there were warnings</returns>
  657. public override string Validate()
  658. {
  659. _validationErrorMessages.Clear();
  660. _validationWarningMessages.Clear();
  661. foreach (SmartLink link in _smartInputLinks)
  662. {
  663. _validationErrorMessages.AddRange (link.GetErrors());
  664. _validationWarningMessages.AddRange (link.GetWarnings());
  665. }
  666. foreach (SmartLink link in _smartOutputLinks)
  667. {
  668. _validationErrorMessages.AddRange (link.GetErrors());
  669. _validationWarningMessages.AddRange (link.GetWarnings());
  670. }
  671. string validationString = "";
  672. foreach (string str in _validationErrorMessages)
  673. {
  674. validationString += "Error: " + str + " ";
  675. }
  676. foreach (string str in _validationWarningMessages)
  677. {
  678. validationString += "Warning: " + str + ". ";
  679. }
  680. return validationString;
  681. }
  682. private void CheckTimeArgumentInGetvaluesMethod(ITime time)
  683. {
  684. if (time is ITimeSpan)
  685. {
  686. if (this._engineApiAccess is IEngine)
  687. {
  688. if (IsLater(((IEngine)this._engineApiAccess).GetTimeHorizon().Start, ((ITimeSpan)time).Start))
  689. {
  690. throw new Exception("GetValues method was invoked using a time argument that representes a time before the allowed time horizon");
  691. }
  692. if (IsLater(((ITimeSpan)time).End, ((IEngine)this._engineApiAccess).GetTimeHorizon().End))
  693. {
  694. throw new Exception("GetValues method was invoked using a time argument that representes a time that is after the allowed time horizon");
  695. }
  696. }
  697. }
  698. else if (time is ITimeStamp)
  699. {
  700. if (this._engineApiAccess is IEngine)
  701. {
  702. if (IsLater(((IEngine)this._engineApiAccess).GetTimeHorizon().Start, (ITimeStamp)time))
  703. {
  704. throw new Exception("GetValues method was invoked using a time argument that representes a time before the allowed time horizon");
  705. }
  706. if (IsLater((ITimeStamp)time, ((IEngine)this._engineApiAccess).GetTimeHorizon().End))
  707. {
  708. throw new Exception("GetValues method was invoked using a time argument that representes a time that is after the allowed time horizon");
  709. }
  710. }
  711. }
  712. else
  713. {
  714. throw new Exception("Illegal data type for time was used in argument to GetValues method. Type must be OpenMI.Standard.ITimeStamp or ITimeSpan");
  715. }
  716. }
  717. private void SendSourceAfterGetValuesCallEvent(ITime time, string LinkID)
  718. {
  719. Oatc.OpenMI.Sdk.Backbone.Event eventA = new Oatc.OpenMI.Sdk.Backbone.Event(EventType.SourceAfterGetValuesCall);
  720. eventA.Description = "GetValues(t = " + ITimeToString(time) + ", ";
  721. eventA.Description += "LinkID: " + LinkID; //TODO: QS = " + _smartOutputLinkSet.GetLink(LinkID).SourceQuantity.ID + " ,QT = " + _smartOutputLinkSet.GetLink(LinkID).TargetQuantity.ID;
  722. eventA.Description += ") <<<===";
  723. eventA.Sender = this;
  724. eventA.SimulationTime = TimeToTimeStamp(_engineApiAccess.GetCurrentTime());
  725. eventA.SetAttribute("GetValues time argument : ",ITimeToString(time));
  726. SendEvent(eventA);
  727. }
  728. private void SendEvent( EventType eventType)
  729. {
  730. Oatc.OpenMI.Sdk.Backbone.Event eventD = new Oatc.OpenMI.Sdk.Backbone.Event(eventType);
  731. eventD.Description = eventType.ToString();
  732. eventD.Sender = this;
  733. eventD.SimulationTime = TimeToTimeStamp(_engineApiAccess.GetCurrentTime());
  734. SendEvent(eventD);
  735. }
  736. }
  737. }