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 }
1 Comment
Unknown User (don)
Looks complicated.
How I'd expect it to be used when it is necessary to convert values and not exchange items. For example to convert values from exchange item containing value as a string to value in exchange item wrapping enum-type values: