Issue
- Remove problem of how DataOperations are defined in standard by showing how a simple change to the interface can let people do whatever they want!
Proposal
- For Transform you could read DataOperation!
Proposed addition to Standard
public interface IExchangeTransform { IExchangeItem ExchangeItemOriginal { set; get; } IExchangeItem ExchangeItemAlternative { get; } IValueSet Transform(IValueSet value); } // Optional Extension for ILinkableComponent interface IExchangeTransformable { int SuggestedTransformsCount { get; } IExchangeTransform TransformSugestion(int index); }
Example
Example of use
static void Transforms() { 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 transformable LinkableComponentTransformable iLCA = new LinkableComponentTransformable(iLC); // change Reed Growth by linear transform y = 10x + 5 int index = iLCA.AddTransformOutput("ReedGrowthHeight", new LinearTransform(10, 5)); IValueSet vs2 = iLCA.GetValues(time, linkid); double d2 = ((IScalarSet)vs2).GetScalar(0); string ida = iLCA.GetOutputExchangeItem(index).Quantity.ID; string idda = iLCA.GetOutputExchangeItem(index).Quantity.Description; }
Wrap a 3rd Party linkable component to make it Transformable
class LinkableComponentTransformable : ILinkableComponent { // Redirect to aggregated linkiable component all members .... #region ILinkableComponent Members #region IPublisher Members // ... except .... public LinkableComponentTransformable(ILinkableComponent iLC) { _iLC = iLC; } public int OutputExchangeItemCount { get { return _iLC.OutputExchangeItemCount + _transformedExchangeItems.Count; } } public IOutputExchangeItem GetOutputExchangeItem(int index) { if (_transformedExchangeItems.ContainsKey(index)) return (IOutputExchangeItem)_transformedExchangeItems[index].ExchangeItemAlternative; return _iLC.GetOutputExchangeItem(index); } public IValueSet GetValues(ITime time, string linkID) { // NOTE: the link must be set up with untransformed exchange item (original) 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 = "ReedGrowthHeightLinTran"; // fudge int index = -1; for (int n = 0; n < iSource.OutputExchangeItemCount; ++n) { if (iSource.GetOutputExchangeItem(n).Quantity.ID == sourceQID) index = n; } if (index > -1) { if (_transformedExchangeItems.ContainsKey(index)) return _transformedExchangeItems[index].Transform(vs); } return vs; } // New Members public int AddTransformOutput(string quantityId, IExchangeTransform transform) { // Not recursive ie no transforms on transforms but could be done int index = OutputExchangeItemCount + _transformedExchangeItems.Count; for (int n = 0; n < OutputExchangeItemCount; ++n) { if (GetOutputExchangeItem(n).Quantity.ID == quantityId) { transform.ExchangeItemOriginal = GetOutputExchangeItem(n); _transformedExchangeItems.Add(index, transform); return index; } } return -1; } Dictionary<int, IExchangeTransform> _transformedExchangeItems = new Dictionary<int, IExchangeTransform>(); ILinkableComponent _iLC; }
Quantity for a Linear Transform
class QuantityLinearTransform : IQuantity { IQuantity _quantity; public QuantityLinearTransform(IQuantity q) { _quantity = q; } #region IQuantity Members public string ID { get { return _quantity.ID + "LinTran"; } } public string Description { get { return _quantity.Description + " Linear Transform"; } } 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 }
A Linear Transform
class LinearTransform : IExchangeTransform { double _a = 1; double _b = 0; IExchangeItem _original; IExchangeItem _new; public LinearTransform(double a, double b) { _a = a; _b = b; } #region IAdaptor Members public IValueSet Transform(IValueSet value) { double x = ((IScalarSet)value).GetScalar(0); double y = _a*x + _b; return new Double(y); } public IExchangeItem ExchangeItemOriginal { set { _original = value; if (value is IOutputExchangeItem) _new = new OutputExchangeItem(new QuantityLinearTransform(_original.Quantity), _original.ElementSet); else { Debug.Assert(false); } } get { return _original; } } public IExchangeItem ExchangeItemAlternative { get { return _new; } } #endregion }
Other classes
SEE ADAPTER EXAMPLE