using System;
using System.Collections.Generic;
using log4net;
using NUnit.Framework;
using Oatc.OpenMI.Sdk.Backbone.IntegrationTests.Components;
using OpenMI.Standard;

namespace Oatc.OpenMI.Sdk.Backbone.IntegrationTests
{
    [TestFixture]
    public class OutputDecoratorTest
    {
        private ILinkableComponent sourceComponent;
        private ILinkableComponent targetComponent1;
        private ILinkableComponent targetComponent2;

        [SetUp]
        public void SetUp()
        {
            sourceComponent = new AnalyticalFunctionComponent();

            targetComponent1 = new AnalyticalFunctionComponent();

            // connect items using decorator
            IOutputItemDecorator unitConverter = new UnitConverter();
            unitConverter.DecoratedOutputItem = sourceComponent.OutputItems[0];
            unitConverter.AddConsumer(targetComponent1.InputItems[0]);

            targetComponent2 = new AnalyticalFunctionComponent();
        }

        // Example1: re-use existing unit converter in 2 different input exchange items

        [Test]
        [Ignore("Test is unfinished, added for OATC discusssion")]
        public void ReuseUnitConverterInTwoComponents()
        {
            ConnectExchangeItemsUsingExistingUnitConverter(sourceComponent, sourceComponent.OutputItems[0], targetComponent2.InputItems[0]);
        }

        public void ConnectExchangeItemsUsingExistingUnitConverter(ILinkableComponent sourceComponent, IOutputItem sourceItem, IInputItem targetItem)
        {
            foreach (var outputItem in sourceComponent.OutputItems)
            {
                if (!(outputItem is IOutputItemDecorator))
                {
                    continue;
                }

                var decorator = (IOutputItemDecorator)outputItem;

                if (decorator.DecoratedOutputItem != sourceItem) // TODO: add more check if needed
                {
                    continue;
                }

                decorator.AddConsumer(targetItem);
                return;
            }
        }

        // Example2: render linkable component including it's decorators
        [Test]
        [Ignore("Test is unfinished, added for OATC discusssion")]
        public void RenderComponent()
        {
            RenderComponent(sourceComponent);
        }

        public void RenderComponent(ILinkableComponent component)
        {
            foreach (var outputItem in sourceComponent.OutputItems)
            {
                if (outputItem is IOutputItemDecorator)
                {
                    DrawOtputItemDecorator((IOutputItemDecorator)outputItem);
                }
                else
                {
                    DrawOutputExchangeItem(outputItem);
                }
            }
        }


        private void DrawOutputExchangeItem(IOutputItem item)
        {
            throw new NotImplementedException();
        }

        private void DrawOtputItemDecorator(IOutputItemDecorator decorator)
        {
            throw new NotImplementedException();
        }

    }
}

Possible implementation of the decorator:

    public class UnitConverter : OutputItem, IOutputItemDecorator
    {
        private new static readonly ILog log = LogManager.GetLogger(typeof (UnitConverter));

        private IOutputItem decoratedOutputItem;
        private readonly IList<IArgument> arguments;

        public UnitConverter()
        {
            arguments = new List<IArgument>();
            arguments.Add(new Argument("SourceUnit", new Unit("m").ToString(), true, "Source unit for conversion (set automatically when DecoratedOutputItem is set"));
            arguments.Add(new Argument("TargetUnit", new Unit("ft").ToString(), true, "Target unit for conversion"));
        }

        public IList<IArgument> Arguments
        {
            get { return arguments; }
        }

        public IOutputItem DecoratedOutputItem
        {
            get { return decoratedOutputItem; }
            set { decoratedOutputItem = value; }
        }

        public void Update()
        {
            log.InfoFormat("Converting units ...");
            foreach (IInputItem targetItem in Consumers)
            {
                targetItem.Values = decoratedOutputItem.Values;

                // TODO: add conversion here
            }
        }
    }
  • No labels