Problem
- Converting IValueSet results to enumerations
Proposal
Additions to Standard
interface IExchangeAdaptor { IExchangeItem ExchangeItemOriginal { set; get; } IExchangeItem ExchangeItemNew { get; } object Adapt(IValueSet value); } // Optional Extension for ILinkableComponent interface IExchangeAdaptable { int SuggestedAdaptorsCount { get; } IExchangeAdaptor AdaptorSugestion(int index); }
Optional change to Standard
class ILinkableComponent { ...... object GetValues(ITime time, string linkID); ...... }
Example
Enumeration
enum ReedGrowth { High = 0, Medium, Low, }
Example of it working
static void Adaptors() { ITime time = new TimeStamp(10.0); string linkid = "wibble"; // has an output exchange item which returns Reed Growth as a height (IScalar/double) ILinkableComponent iLC = new LinkableComponentReedGrowth(); IValueSet vs = iLC.GetValues(time, linkid); double d = ((IScalarSet)vs).GetScalar(0); string id = iLC.GetOutputExchangeItem(0).Quantity.ID; string idd = iLC.GetOutputExchangeItem(0).Quantity.Description; // make 3rd party Linkable component adaptable LinkableComponentAdaptable iLCA = new LinkableComponentAdaptable(iLC); // change Reed Growth to an enum ReedGrowth { High = 0, Medium, Low, } int index = iLCA.MakeAdaption("ReedGrowthHeight", new ReedGrowthEnum()); ReedGrowth growth = (ReedGrowth)iLCA.GetValuesAdapted(time, linkid); string ida = iLCA.GetOutputExchangeItem(index).Quantity.ID; string idda = iLCA.GetOutputExchangeItem(index).Quantity.Description; // Another proposed change: // object GetValues(time, linkid, out bool adapted); // if adapted false then IValueSet returned, else user needs to test against 'as' ie ... object o = iLCA.GetValuesAdapted(time, linkid); if (o is ReedGrowth) { ReedGrowth gr = (ReedGrowth)o; bool badGrowth = gr == ReedGrowth.High; } }
Wrapped LinkableComponent to allow Adaption
class LinkableComponentAdaptable : ILinkableComponent { // Redirect to aggregated linkiable component all members .... #region ILinkableComponent Members #region IPublisher Members // ... except .... public LinkableComponentAdaptable(ILinkableComponent iLC) { _iLC = iLC; } public int OutputExchangeItemCount { get { return _iLC.OutputExchangeItemCount; } } public IOutputExchangeItem GetOutputExchangeItem(int index) { IOutputExchangeItem item = _iLC.GetOutputExchangeItem(index); if (_adaptedExchangeItems.ContainsKey(item)) return (IOutputExchangeItem)_adaptedExchangeItems[item].ExchangeItemNew; return item; } public IValueSet GetValues(ITime time, string linkID) { return _iLC.GetValues(time, linkID); } public object GetValuesAdapted(ITime time, string linkID) { IValueSet vs = _iLC.GetValues(time, linkID); /* * from linkid get iLink * from iLink get sourceComponent * from iLink get sourceQuantity.ID * fudged below .... */ ILinkableComponent iSource = this; // fudge string sourceQID = "ReedGrowthHeightEnum"; // fudge int index = -1; for (int n = 0; n < iSource.OutputExchangeItemCount; ++n) { if (iSource.GetOutputExchangeItem(n).Quantity.ID == sourceQID) index = n; } if (index > -1) { IOutputExchangeItem item = _iLC.GetOutputExchangeItem(index); if (_adaptedExchangeItems.ContainsKey(item)) return _adaptedExchangeItems[item].Adapt(vs); } return vs; } // New Members public int MakeAdaption(string quantityId, IExchangeAdaptor adaptor) { for (int n = 0; n < OutputExchangeItemCount; ++n) { if (GetOutputExchangeItem(n).Quantity.ID == quantityId) { adaptor.ExchangeItemOriginal = GetOutputExchangeItem(n); _adaptedExchangeItems.Add(GetOutputExchangeItem(n), adaptor); return n; } } return -1; } Dictionary<IOutputExchangeItem, IExchangeAdaptor> _adaptedExchangeItems = new Dictionary<IOutputExchangeItem, IExchangeAdaptor>(); ILinkableComponent _iLC; }
Quantity for Reed Growth Enumeration
class QuantityAsEnum : IQuantity { IQuantity _quantity; public QuantityAsEnum(IQuantity q) { _quantity = q; } #region IQuantity Members public string ID { get { return _quantity.ID + "Enum"; } } public string Description { get { return _quantity.Description + " Adapted to enumeration return value"; } } public org.OpenMI.Standard.ValueType ValueType { get { return _quantity.ValueType; } } public IDimension Dimension { get { return _quantity.Dimension; } } public IUnit Unit { get { return _quantity.Unit; } } #endregion }
Adapter to make Reed Growth an enum
class ReedGrowthEnum : IExchangeAdaptor { double _high = 15; double _low = 5; IExchangeItem _original; IExchangeItem _new; #region IAdaptor Members public object Adapt(IValueSet value) { ReedGrowth rg = ReedGrowth.Medium; double d = ((IScalarSet)value).GetScalar(0); if (d > _high) rg = ReedGrowth.High; if (d < _low) rg = ReedGrowth.Low; return rg; } public IExchangeItem ExchangeItemOriginal { set { _original = value; if (value is IInputExchangeItem) _new = new InputExchangeItem(new QuantityAsEnum(_original.Quantity), _original.ElementSet); else if (value is IOutputExchangeItem) _new = new OutputExchangeItem(new QuantityAsEnum(_original.Quantity), _original.ElementSet); else { Debug.Assert(false); } } get { return _original; } } public IExchangeItem ExchangeItemNew { get { return _new; } } #endregion }
Original LinkableComponent with Reed Growth as a double
class LinkableComponentReedGrowth : ILinkableComponent { #region ILinkableComponent Members #region IPublisher Members public int OutputExchangeItemCount { get { return 1; } } public IOutputExchangeItem GetOutputExchangeItem(int index) { return index == 0 ? _reeds : null; } public IValueSet GetValues(ITime time, string linkID) { return new Double(12); } ReedGrowthHeight _reeds = new ReedGrowthHeight(); }
Reed growth as double Output Exchange Item
class ReedGrowthHeight : IOutputExchangeItem { #region IOutputExchangeItem Members #region IExchangeItem Members public IQuantity Quantity { get { return _quantity; } } public IElementSet ElementSet { get { return null; } } #endregion ReedGrowthQuantity _quantity = new ReedGrowthQuantity(); }
Reed Growth as double Quantity
class ReedGrowthQuantity : IQuantity { #region IQuantity Members public string ID { get { return "ReedGrowthHeight"; } } public string Description { get { return "ReedGrowthHeight as a scalor"; } } public org.OpenMI.Standard.ValueType ValueType { get { return org.OpenMI.Standard.ValueType.Scalar; } } public IDimension Dimension { get { return null; } } public IUnit Unit { get { return null; } } #endregion }
Util to give me a IScalerSet from a double
class Double : IScalarSet { double _double; public Double(double d) { _double = d; } #region IScalarSet Members public double GetScalar(int index) { return IsValid(index) ? _double : -999.999; } #endregion #region IValueSet Members public int Count { get { return 1; } } public bool IsValid(int index) { return index == 0; } #endregion }