public LinkableComponentOpenMIV1Wrapper(ILinkableComponentVersion1 component1, 
            IDocumentAccessor accessor,
            List<Utilities.Standard1.Argument1> args1)
            : base(new Identity(component1.ComponentID,
                    component1.ModelID + " [OpenMIv1]", component1.ComponentDescription),
                new ExternalType(typeof(LinkableComponentOpenMIV1Wrapper)),
                new ExternalType(typeof(EngineProxy)))
        {
            Description += "\r\nConverted from OpenMI Standard 1";

            DocumentAccessor = accessor;

            var uriPersistence = InitialiseArguments(component1, args1);

            ConstuctComponent(component1, uriPersistence, args1);
        }
        public LinkableComponentFluidEarthV1Wrapper(ILinkableComponentVersion1 component1, 
            IDocumentAccessor accessor,
            List<Utilities.Standard1.Argument1> args1)
            : base(new Identity(component1.ComponentID,
                    component1.ModelID + " [FluidEarthV1]", component1.ComponentDescription),
                new ExternalType(typeof(LinkableComponentOpenMIV1Wrapper)),
                new ExternalType(typeof(IProxyEngine5)),
                true)
        {
            _includeUpdateTimeInterval = false;

            Description += "\r\nUsing FluidEarth V1";

            DocumentAccessor = accessor;

            var uriPersistence = InitialiseArguments(component1, args1);

            SetDefaultArguments();

            ConstuctComponent(component1, uriPersistence, args1);
        }
            public void PrePrepare(
               LinkableComponentOpenMIV1Wrapper component2,
               IExternalType component1ExternalType, 
               double startTime, double updateLinkTimeIncrement,
               List<IBaseInput> activeInputs, List<IBaseOutput> activeOutputs)
            {
                Type tComponentV1;

                Component1
                    = component1ExternalType.CreateInstance(out tComponentV1)
                    as OpenMI.Standard.ILinkableComponent;

                if (Component1 == null)
                    throw new Exception("Cannot instantiate " + component1ExternalType.ToString());

                Component1.Initialize(component2.Arguments1.ToArray());

                _currentTime = startTime;
                _updateLinkTimeIncrement = updateLinkTimeIncrement;

                   // Create internal links between components 1 and 2
                   // T2 --> T1
                   // S1 --> S2

                Utilities.Standard1.TimeSpan timeHorizon1
                    = new Utilities.Standard1.TimeSpan(component2.TimeExtent.TimeHorizon);

                OpenMI.Standard.IInputExchangeItem input;
                OpenMI.Standard.IOutputExchangeItem output;
                OpenMI.Standard.ILink internalLink;

                ITimeSpaceExchangeItem itemTimeSpace;

                string idQuantity, idElementSet;

                activeInputs.ForEach(i =>
                    {
                        idQuantity = i.ValueDefinition.Caption;

                        itemTimeSpace = i as ITimeSpaceExchangeItem;
                        idElementSet = itemTimeSpace == null
                            ? i.Caption // what else?
                            : itemTimeSpace.SpatialDefinition.Caption;

                        internalLink = null;

                        for (int n = 0; n < _component1.InputExchangeItemCount; ++n)
                        {
                            input = _component1.GetInputExchangeItem(n);

                            if (input.Quantity.ID != idQuantity
                                || input.ElementSet.ID != idElementSet)
                                continue;

                            var isVector = input.Quantity.ValueType == OpenMI.Standard.ValueType.Vector;

                            // Get providers convertot to use directly

                            Contract.Requires(i.Provider is IHasValueSetConvertor,
                                "i.Provider is IHasValueSetConvertor");

                            var convertorProvider = ((IHasValueSetConvertor)i.Provider).ValueSetConverter
                                as IValueSetConverterTime;

                            Contract.Requires(convertorProvider != null,
                                "i.Provider.ValueSetConverter is IValueSetConverterTime");

                            internalLink = new Utilities.Standard1.InternalLink(
                                _component1, input, timeHorizon1, convertorProvider, isVector);

                            _linksIn.Add(internalLink);

                            _component1.AddLink(internalLink);

                            break;
                        }

                        if (internalLink == null)
                            throw new Exception(string.Format(
                                "OpenMI.Standard.IOutputExchangeItem not found with Qualtity,ElementSet ids if \"{0}\",\"{1}\"",
                                idQuantity, idElementSet));
                    });

                activeOutputs.ForEach(o =>
                    {
                        idQuantity = o.ValueDefinition.Caption;

                        itemTimeSpace = o as ITimeSpaceExchangeItem;
                        idElementSet = itemTimeSpace == null
                            ? o.Caption // what else?
                            : itemTimeSpace.SpatialDefinition.Caption;

                        internalLink = null;

                        for (int n = 0; n < _component1.OutputExchangeItemCount; ++n)
                        {
                            output = _component1.GetOutputExchangeItem(n);

                            if (output.Quantity.ID != idQuantity
                                || output.ElementSet.ID != idElementSet)
                                continue;

                            internalLink = new Utilities.Standard1.InternalLink(_component1, output, timeHorizon1);

                            _linksOut.Add(internalLink);

                            _component1.AddLink(internalLink);

                            if (((IHasValueSetConvertor)o).ValueSetConverter is ValueSetConverterTimeEngineDoubleStandard1)
                            {
                                var convertor = (ValueSetConverterTimeEngineDoubleStandard1)((IHasValueSetConvertor)o).ValueSetConverter;

                                //convertor.SetRuntime(this, internalLink);
                            }
                            else if (((IHasValueSetConvertor)o).ValueSetConverter is ValueSetConverterTimeEngineDoubleVector3dStandard1)
                            {
                                var convertor = (ValueSetConverterTimeEngineDoubleVector3dStandard1)((IHasValueSetConvertor)o).ValueSetConverter;

                                //convertor.SetRuntime(this, internalLink);
                            }
                            else
                                throw new Exception("o.ValueSetConverter as ValueSetConverterTimeEngineDouble?");

                            break;
                        }

                        if (internalLink == null)
                            throw new Exception(string.Format(
                                "OpenMI.Standard.IInputExchangeItem not found with Qualtity,ElementSet ids if \"{0}\",\"{1}\"",
                                idQuantity, idElementSet));
                    });

                if (_linksOut.Count < 1)
                    throw new Exception("At least one output link must be specified");
            }
        void ConstructExchangeItems(ILinkableComponentVersion1 component1, 
            Dictionary<string, Utilities.Standard1.ExchangeItemV1ModelXml> v1ModelXmlInputs,
            Dictionary<string, Utilities.Standard1.ExchangeItemV1ModelXml> v1ModelXmlOutputs)
        {
            List<BaseInput> convertedInputs = new List<BaseInput>();
            List<BaseOutput> convertedOutputs = new List<BaseOutput>();

            OpenMI.Standard.IInputExchangeItem input1;
            string engineVariable, description;
            Utilities.Standard1.ExchangeItemV1ModelXml v1Model;

            for (int n = 0; n < component1.InputExchangeItemCount; ++n)
            {
                input1 = component1.GetInputExchangeItem(n);

                v1Model = v1ModelXmlInputs
                    .Values
                    .Where(v =>
                        v.Quantity.Id == input1.Quantity.ID
                        && v.ElementSet.Id == input1.ElementSet.ID)
                    .SingleOrDefault();

                engineVariable = EngineVariable(
                    string.Format("Input{0}", n),
                    input1.Quantity.ID, input1.ElementSet.ID);

                description = string.Format("{0}\r\n{1}",
                    input1.Quantity.Description, input1.ElementSet.Description);

                convertedInputs.Add(
                    NewInputSpaceTime(engineVariable, description,
                        input1, v1Model, input1.ElementSet.ElementCount));
            }

            OpenMI.Standard.IOutputExchangeItem output1;

            for (int n = 0; n < component1.OutputExchangeItemCount; ++n)
            {
                output1 = component1.GetOutputExchangeItem(n);

                v1Model = v1ModelXmlOutputs
                    .Values
                    .Where(v =>
                        v.Quantity.Id == output1.Quantity.ID
                        && v.ElementSet.Id == output1.ElementSet.ID)
                    .SingleOrDefault();

                engineVariable = EngineVariable(
                    string.Format("Output{0}", n),
                    output1.Quantity.ID, output1.ElementSet.ID);

                description = string.Format("{0}\r\n{1}",
                    output1.Quantity.Description, output1.ElementSet.Description);

                convertedOutputs.Add(
                    NewOutputSpaceTime(engineVariable, description,
                        output1, v1Model, output1.ElementSet.ElementCount));
            }

            AddRange(convertedInputs);
            AddRange(convertedOutputs);
        }
        void Construct(ILinkableComponentVersion1 component1, List<Utilities.Standard1.Argument1> args1)
        {
            Utilities.Standard1.Argument1 argModelResource = args1
                .Where(a => a.Key == "FluidEarth_SDK.ArgResource.Model")
                .SingleOrDefault();

            if (argModelResource != null)
            {
                // If necessary can automate this
                StringBuilder sb = new StringBuilder();

                sb.AppendLine("Model file is an Embedded Resources, need to unpack");
                sb.AppendLine("On command line, run component assembly with argument \"unpack\" e.g.");
                sb.AppendLine(">FluidEarth_Example_TankCs.exe unpack");
                sb.AppendLine("Then REMOVE omi argument FluidEarth_SDK.ArgResource.Model and REPLACE with");
                sb.AppendLine("FluidEarth_SDK.ArgFile.Model");
                sb.AppendLine("with value set to the unpacked model file");

                throw new Exception(sb.ToString());
            }

            Utilities.Standard1.Argument1 argModelFile = args1
                .Where(a => a.Key == "FluidEarth_SDK.ArgFile.Model")
                .SingleOrDefault();

            if (argModelFile == null) // further back in history?
                argModelFile = args1
                .Where(a => a.Key == "OpenWEB_SDK.ArgFile.Model")
                .SingleOrDefault();

            Dictionary<string, Utilities.Standard1.ExchangeItemV1ModelXml> v1ModelXmlInputs = null;
            Dictionary<string, Utilities.Standard1.ExchangeItemV1ModelXml> v1ModelXmlOutputs = null;

            if (argModelFile != null)
            {
                XDocument doc = XDocument.Load(argModelFile.Value);
                XElement xModel = doc.Root;

                Utilities.Standard1.ReadModelFile(xModel, out v1ModelXmlInputs, out v1ModelXmlOutputs);
            }

            ConstructExchangeItems(component1, v1ModelXmlInputs, v1ModelXmlOutputs);

            string captionSpatialDefintion, captionValueDefintion;
            ITimeSpaceExchangeItem spatial;

            if (v1ModelXmlInputs != null)
            {
                foreach (Utilities.Standard1.ExchangeItemV1ModelXml e in v1ModelXmlInputs.Values)
                {
                    captionValueDefintion = e.Quantity.Id;
                    captionSpatialDefintion = e.ElementSet.Id;

                    foreach (IBaseInput input in _inputs)
                    {
                        if (input.ValueDefinition.Caption != captionValueDefintion)
                            continue;

                        spatial = input as ITimeSpaceExchangeItem;

                        if (spatial == null)
                            continue;

                        //if (spatial.SpatialDefinition.Caption == captionSpatialDefintion)
                        //    ((InputSpaceTime)input).AddUserVariables(e.UserVariables);
                    }
                }
            }

            if (v1ModelXmlOutputs != null)
            {
                foreach (Utilities.Standard1.ExchangeItemV1ModelXml e in v1ModelXmlOutputs.Values)
                {
                    captionValueDefintion = e.Quantity.Id;
                    captionSpatialDefintion = e.ElementSet.Id;

                    foreach (IBaseOutput output in _outputs)
                    {
                        if (output.ValueDefinition.Caption != captionValueDefintion)
                            continue;

                        spatial = output as ITimeSpaceExchangeItem;

                        if (spatial == null)
                            continue;

                        //if (spatial.SpatialDefinition.Caption == captionSpatialDefintion)
                        //    ((OutputSpaceTime)output).AddUserVariables(e.UserVariables);
                    }
                }
            }
        }
        protected virtual ArgumentUri InitialiseArguments(ILinkableComponentVersion1 component1, List<Utilities.Standard1.Argument1> args1)
        {
            if (component1 == null)
            {
                var uri = new Uri(@"http://sourceforge.net/projects/fluidearth/");
                var persistence = new ArgumentUri(GetArgumentIdentity(ArgsV1Wrapper.Persistence), uri);

                // For Uri's have to use a valid Url to initialise, then change to relevant value
                Arguments.Add(persistence);
                Arguments.Add(new ArgumentExternalType(GetArgumentIdentity(ArgsV1Wrapper.EngineExternalType),
                    new ExternalType(DocumentAccessor)));

                if (_includeUpdateTimeInterval)
                    Arguments.Add(new ArgumentTimeInterval(GetArgumentIdentity(ArgsV1Wrapper.UpdateTimeInterval),
                        new TimeInterval()));

                if (args1 != null)
                    foreach (var a1 in args1)
                        Arguments.Add(new ArgumentStandard1(a1));

                return persistence;
            }

            ArgumentTimeHorizon = new Time(
                component1.TimeHorizon.Start.ModifiedJulianDay,
                component1.TimeHorizon.End.ModifiedJulianDay);

            ExternalType component1Type = new ExternalType(DocumentAccessor);
            component1Type.Initialise(component1.GetType());

            var uriP = new Uri(
                DocumentAccessor.Uri
                    .LocalPath
                    .Substring(0, DocumentAccessor.Uri.LocalPath.LastIndexOf('.')) + Caption + "Persist.xml");

            var uriPersistence = new ArgumentUri(GetArgumentIdentity(ArgsV1Wrapper.Persistence), uriP);

            uriPersistence.ValueAsString =
                new Uri(
                    DocumentAccessor.Uri
                        .LocalPath
                        .Substring(0, DocumentAccessor.Uri.LocalPath.LastIndexOf('.')) + Caption + "Persist.xml")
                .AbsoluteUri;

            Arguments.Add(uriPersistence);
            Arguments.Add(new ArgumentExternalType(GetArgumentIdentity(ArgsV1Wrapper.EngineExternalType),
                component1Type));

            if (_includeUpdateTimeInterval)
                Arguments.Add(new ArgumentTimeInterval(GetArgumentIdentity(ArgsV1Wrapper.UpdateTimeInterval),
                    new TimeInterval()));

            foreach (var a1 in args1)
                Arguments.Add(new ArgumentStandard1(a1));

            return uriPersistence;
        }
        protected void ConstuctComponent(ILinkableComponentVersion1 component1,
            ArgumentUri uriPersistence,
            List<Utilities.Standard1.Argument1> args1)
        {
            try
            {
                _convertingFromV1 = true;

                Construct(component1, args1);

                Initialize();

                var uri = (uriPersistence.Value as ArgumentValueUri).Value;

                var xPersistence = new XDocument(Persist(DocumentAccessor));
                xPersistence.Save(uri.LocalPath);
            }
            finally
            {
                _convertingFromV1 = false;
            }
        }