public async Task VerifyThatCloseModelWorks()
        {
            var siteDir     = new CDP4Common.SiteDirectoryData.SiteDirectory(Guid.NewGuid(), null, null);
            var modelRdlDto = new CDP4Common.DTO.ModelReferenceDataLibrary {
                Iid = Guid.NewGuid()
            };
            var siteDirDto = new CDP4Common.DTO.SiteDirectory {
                Iid = Guid.NewGuid()
            };
            var requiredPocoDto = new CDP4Common.DTO.SiteReferenceDataLibrary {
                Iid = Guid.NewGuid()
            };
            var containerEngModelSetupDto = new EngineeringModelSetup {
                Iid = Guid.NewGuid()
            };
            var containerEngModelSetup = new CDP4Common.SiteDirectoryData.EngineeringModelSetup {
                Iid = containerEngModelSetupDto.Iid
            };
            var iterationDto = new Iteration {
                Iid = Guid.NewGuid()
            };
            var iteration = new CDP4Common.EngineeringModelData.Iteration {
                Iid = iterationDto.Iid
            };
            var iterationSetupDto = new CDP4Common.DTO.IterationSetup {
                Iid = Guid.NewGuid(), IterationIid = iterationDto.Iid
            };

            iterationDto.IterationSetup = iterationSetupDto.IterationIid;
            siteDir.Model.Add(containerEngModelSetup);
            modelRdlDto.RequiredRdl = requiredPocoDto.Iid;

            var credentials = new Credentials("admin", "pass", new Uri("http://www.rheagroup.com"));
            var session2    = new Session(this.mockedDal.Object, credentials);

            var iterationSetup = new CDP4Common.SiteDirectoryData.IterationSetup {
                Iid = iterationSetupDto.Iid, Container = containerEngModelSetup, IterationIid = iteration.Iid
            };
            var thingsToAdd = new List <Thing> {
                siteDirDto, requiredPocoDto, containerEngModelSetupDto, modelRdlDto, iterationSetupDto
            };

            await session2.Assembler.Synchronize(thingsToAdd);

            var lazyiteration = new Lazy <CDP4Common.CommonData.Thing>(() => iteration);

            session2.Assembler.Cache.GetOrAdd(new CacheKey(iterationDto.Iid, null), lazyiteration);

            CDP4Common.CommonData.Thing changedObject = null;
            CDPMessageBus.Current.Listen <ObjectChangedEvent>(typeof(CDP4Common.EngineeringModelData.Iteration)).Subscribe(x => changedObject = x.ChangedThing);
            await session2.CloseIterationSetup(iterationSetup);

            Assert.NotNull(changedObject);
        }
        /// <summary>
        /// Insert a new database record from the supplied data transfer object.
        /// </summary>
        /// <param name="transaction">
        /// The current <see cref="NpgsqlTransaction"/> to the database.
        /// </param>
        /// <param name="partition">
        /// The database partition (schema) where the requested resource will be stored.
        /// </param>
        /// <param name="engineeringModelSetup">
        /// The engineeringModelSetup DTO that is to be persisted.
        /// </param>
        /// <param name="container">
        /// The container of the DTO to be persisted.
        /// </param>
        /// <returns>
        /// True if the concept was successfully persisted.
        /// </returns>
        public virtual bool Write(NpgsqlTransaction transaction, string partition, CDP4Common.DTO.EngineeringModelSetup engineeringModelSetup, CDP4Common.DTO.Thing container = null)
        {
            bool isHandled;
            var  valueTypeDictionaryAdditions = new Dictionary <string, string>();
            var  beforeWrite = this.BeforeWrite(transaction, partition, engineeringModelSetup, container, out isHandled, valueTypeDictionaryAdditions);

            if (!isHandled)
            {
                beforeWrite = beforeWrite && base.Write(transaction, partition, engineeringModelSetup, container);

                var valueTypeDictionaryContents = new Dictionary <string, string>
                {
                    { "EngineeringModelIid", !this.IsDerived(engineeringModelSetup, "EngineeringModelIid") ? engineeringModelSetup.EngineeringModelIid.ToString() : string.Empty },
                    { "Kind", !this.IsDerived(engineeringModelSetup, "Kind") ? engineeringModelSetup.Kind.ToString() : string.Empty },
                    { "SourceEngineeringModelSetupIid", !this.IsDerived(engineeringModelSetup, "SourceEngineeringModelSetupIid") && engineeringModelSetup.SourceEngineeringModelSetupIid.HasValue ? engineeringModelSetup.SourceEngineeringModelSetupIid.Value.ToString() : null },
                    { "StudyPhase", !this.IsDerived(engineeringModelSetup, "StudyPhase") ? engineeringModelSetup.StudyPhase.ToString() : string.Empty },
                }.Concat(valueTypeDictionaryAdditions).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

                using (var command = new NpgsqlCommand())
                {
                    var sqlBuilder = new System.Text.StringBuilder();

                    sqlBuilder.AppendFormat("INSERT INTO \"{0}\".\"EngineeringModelSetup\"", partition);
                    sqlBuilder.AppendFormat(" (\"Iid\", \"ValueTypeDictionary\", \"Container\", \"DefaultOrganizationalParticipant\")");
                    sqlBuilder.AppendFormat(" VALUES (:iid, :valueTypeDictionary, :container, :defaultOrganizationalParticipant);");

                    command.Parameters.Add("iid", NpgsqlDbType.Uuid).Value = engineeringModelSetup.Iid;
                    command.Parameters.Add("valueTypeDictionary", NpgsqlDbType.Hstore).Value            = valueTypeDictionaryContents;
                    command.Parameters.Add("container", NpgsqlDbType.Uuid).Value                        = container.Iid;
                    command.Parameters.Add("defaultOrganizationalParticipant", NpgsqlDbType.Uuid).Value = !this.IsDerived(engineeringModelSetup, "DefaultOrganizationalParticipant") ? Utils.NullableValue(engineeringModelSetup.DefaultOrganizationalParticipant) : Utils.NullableValue(null);

                    command.CommandText = sqlBuilder.ToString();
                    command.Connection  = transaction.Connection;
                    command.Transaction = transaction;

                    this.ExecuteAndLogCommand(command);
                }
                engineeringModelSetup.ActiveDomain.ForEach(x => this.AddActiveDomain(transaction, partition, engineeringModelSetup.Iid, x));
            }

            return(this.AfterWrite(beforeWrite, transaction, partition, engineeringModelSetup, container));
        }
        /// <summary>
        /// Update a database record from the supplied data transfer object.
        /// </summary>
        /// <param name="transaction">
        /// The current transaction to the database.
        /// </param>
        /// <param name="partition">
        /// The database partition (schema) where the requested resource will be updated.
        /// </param>
        /// <param name="engineeringModelSetup">
        /// The engineeringModelSetup DTO that is to be updated.
        /// </param>
        /// <param name="container">
        /// The container of the DTO to be updated.
        /// </param>
        /// <returns>
        /// True if the concept was successfully updated.
        /// </returns>
        public virtual bool Update(NpgsqlTransaction transaction, string partition, CDP4Common.DTO.EngineeringModelSetup engineeringModelSetup, CDP4Common.DTO.Thing container = null)
        {
            bool isHandled;
            var  valueTypeDictionaryAdditions = new Dictionary <string, string>();
            var  beforeUpdate = this.BeforeUpdate(transaction, partition, engineeringModelSetup, container, out isHandled, valueTypeDictionaryAdditions);

            if (!isHandled)
            {
                beforeUpdate = beforeUpdate && base.Update(transaction, partition, engineeringModelSetup, container);

                var valueTypeDictionaryContents = new Dictionary <string, string>
                {
                    { "Kind", !this.IsDerived(engineeringModelSetup, "Kind") ? engineeringModelSetup.Kind.ToString() : string.Empty },
                    { "StudyPhase", !this.IsDerived(engineeringModelSetup, "StudyPhase") ? engineeringModelSetup.StudyPhase.ToString() : string.Empty },
                    { "EngineeringModelIid", !this.IsDerived(engineeringModelSetup, "EngineeringModelIid") ? engineeringModelSetup.EngineeringModelIid.ToString() : string.Empty },
                    { "SourceEngineeringModelSetupIid", !this.IsDerived(engineeringModelSetup, "SourceEngineeringModelSetupIid") && engineeringModelSetup.SourceEngineeringModelSetupIid.HasValue ? engineeringModelSetup.SourceEngineeringModelSetupIid.Value.ToString() : null },
                }.Concat(valueTypeDictionaryAdditions).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

                using (var command = new NpgsqlCommand())
                {
                    var sqlBuilder = new System.Text.StringBuilder();

                    sqlBuilder.AppendFormat("UPDATE \"{0}\".\"EngineeringModelSetup\"", partition);
                    sqlBuilder.AppendFormat(" SET (\"Container\", \"ValueTypeDictionary\")");
                    sqlBuilder.AppendFormat(" = (:container, \"ValueTypeDictionary\" || :valueTypeDictionary)");
                    sqlBuilder.AppendFormat(" WHERE \"Iid\" = :iid;");
                    command.Parameters.Add("iid", NpgsqlDbType.Uuid).Value                   = engineeringModelSetup.Iid;
                    command.Parameters.Add("container", NpgsqlDbType.Uuid).Value             = container.Iid;
                    command.Parameters.Add("valueTypeDictionary", NpgsqlDbType.Hstore).Value = valueTypeDictionaryContents;

                    command.CommandText = sqlBuilder.ToString();
                    command.Connection  = transaction.Connection;
                    command.Transaction = transaction;
                    this.ExecuteAndLogCommand(command);
                }
            }

            return(this.AfterUpdate(beforeUpdate, transaction, partition, engineeringModelSetup, container));
        }
        public async Task VerifyThatCloseModelRdlWorks()
        {
            var siteDir = new CDP4Common.SiteDirectoryData.SiteDirectory(Guid.NewGuid(), null, null);
            var JohnDoe = new CDP4Common.SiteDirectoryData.Person(this.person.Iid, this.session.Assembler.Cache, this.uri)
            {
                ShortName = "John"
            };
            var modelRdlDto = new CDP4Common.DTO.ModelReferenceDataLibrary()
            {
                Iid = Guid.NewGuid()
            };
            var siteDirDto = new CDP4Common.DTO.SiteDirectory()
            {
                Iid = Guid.NewGuid()
            };
            var requiredPocoDto = new CDP4Common.DTO.SiteReferenceDataLibrary()
            {
                Iid = Guid.NewGuid()
            };
            var requiredPocoRdl           = new SiteReferenceDataLibrary(Guid.NewGuid(), null, null);
            var containerEngModelSetupDto = new EngineeringModelSetup()
            {
                Iid = Guid.NewGuid()
            };
            var containerEngModelSetup = new CDP4Common.SiteDirectoryData.EngineeringModelSetup()
            {
                Iid = containerEngModelSetupDto.Iid
            };

            siteDir.Model.Add(containerEngModelSetup);
            modelRdlDto.RequiredRdl = requiredPocoDto.Iid;
            siteDir.Person.Add(JohnDoe);

            var credentials = new Credentials("admin", "pass", new Uri("http://www.rheagroup.com"));
            var session2    = new Session(this.mockedDal.Object, credentials);

            session2.GetType().GetProperty("ActivePerson").SetValue(session2, JohnDoe, null);

            var modelRdlPoco = new ModelReferenceDataLibrary {
                Iid = modelRdlDto.Iid, Name = modelRdlDto.Name, ShortName = modelRdlDto.ShortName, Container = containerEngModelSetup, RequiredRdl = requiredPocoRdl
            };
            var thingsToAdd = new List <Thing>()
            {
                siteDirDto, requiredPocoDto, containerEngModelSetupDto, modelRdlDto
            };

            await session2.Assembler.Synchronize(thingsToAdd);

            await session2.Read(modelRdlPoco);

            Assert.AreEqual(2, session2.OpenReferenceDataLibraries.ToList().Count());

            Lazy <CDP4Common.CommonData.Thing> rdlPocoToClose;

            session2.Assembler.Cache.TryGetValue(new CacheKey(modelRdlPoco.Iid, null), out rdlPocoToClose);
            Assert.NotNull(rdlPocoToClose);
            await session2.CloseModelRdl((ModelReferenceDataLibrary)rdlPocoToClose.Value);

            // Checkt that closing a modelRDL doesn't close it's required SiteRDL
            Assert.AreEqual(1, session2.OpenReferenceDataLibraries.ToList().Count());
            Assert.AreEqual(ClassKind.SiteReferenceDataLibrary, session2.OpenReferenceDataLibraries.First().ClassKind);
        }
        public async Task VerifyThatSiteRdlRequiredByModelRdlCannotBeClosed()
        {
            var rdlDto = new CDP4Common.DTO.SiteReferenceDataLibrary {
                Iid = Guid.NewGuid()
            };
            var siteDirDto = new CDP4Common.DTO.SiteDirectory {
                Iid = Guid.NewGuid()
            };
            var requiredRdlDto = new CDP4Common.DTO.SiteReferenceDataLibrary()
            {
                Iid = Guid.NewGuid()
            };

            rdlDto.RequiredRdl = requiredRdlDto.Iid;
            siteDirDto.SiteReferenceDataLibrary.Add(rdlDto.Iid);
            siteDirDto.SiteReferenceDataLibrary.Add(requiredRdlDto.Iid);

            siteDirDto.Person.Add(this.person.Iid);

            var mrdl = new CDP4Common.DTO.ModelReferenceDataLibrary(Guid.NewGuid(), 0)
            {
                RequiredRdl = requiredRdlDto.Iid
            };
            var modelsetup = new EngineeringModelSetup(Guid.NewGuid(), 0);

            modelsetup.RequiredRdl.Add(mrdl.Iid);

            var model = new EngineeringModel(Guid.NewGuid(), 0)
            {
                EngineeringModelSetup = modelsetup.Iid
            };
            var iteration = new Iteration(Guid.NewGuid(), 0);

            model.Iteration.Add(iteration.Iid);

            siteDirDto.Model.Add(modelsetup.Iid);

            var readReturn = new List <Thing>
            {
                siteDirDto,
                mrdl,
                modelsetup,
                model,
                iteration,
                this.person
            };

            var mrdlpoco       = new ModelReferenceDataLibrary(mrdl.Iid, null, null);
            var modelsetuppoco = new CDP4Common.SiteDirectoryData.EngineeringModelSetup(modelsetup.Iid, null, null);

            modelsetuppoco.RequiredRdl.Add(mrdlpoco);

            var participant = new CDP4Common.DTO.Participant(Guid.NewGuid(), 0)
            {
                Person = this.person.Iid
            };

            modelsetup.Participant.Add(participant.Iid);
            var modelPoco = new CDP4Common.EngineeringModelData.EngineeringModel(model.Iid, null, null)
            {
                EngineeringModelSetup = modelsetuppoco
            };
            var iterationPoco = new CDP4Common.EngineeringModelData.Iteration(iteration.Iid, null, null);

            modelPoco.Iteration.Add(iterationPoco);

            var readTaskCompletionSource = new TaskCompletionSource <IEnumerable <Thing> >();

            readTaskCompletionSource.SetResult(readReturn);
            this.mockedDal.Setup(
                x => x.Read(It.IsAny <Iteration>(), It.IsAny <CancellationToken>(), null))
            .Returns(readTaskCompletionSource.Task);

            var thingsToAdd = new List <Thing>()
            {
                siteDirDto, requiredRdlDto, rdlDto, this.person, participant, modelsetup
            };

            await this.session.Assembler.Synchronize(thingsToAdd);

            var JohnDoe = this.session.RetrieveSiteDirectory().Person.Single(x => x.Iid == this.person.Iid);

            this.session.GetType().GetProperty("ActivePerson").SetValue(this.session, JohnDoe, null);

            await this.session.Read(iterationPoco, null);

            Assert.AreEqual(2, this.session.OpenReferenceDataLibraries.Count());

            Lazy <CDP4Common.CommonData.Thing> requiredRdlToClose;

            this.session.Assembler.Cache.TryGetValue(new CacheKey(requiredRdlDto.Iid, null), out requiredRdlToClose);

            await this.session.CloseRdl((SiteReferenceDataLibrary)requiredRdlToClose.Value);

            Assert.AreEqual(2, this.session.OpenReferenceDataLibraries.Count());
        }
        /// <summary>
        /// The mapping from a database record to data transfer object.
        /// </summary>
        /// <param name="reader">
        /// An instance of the SQL reader.
        /// </param>
        /// <returns>
        /// A deserialized instance of <see cref="CDP4Common.DTO.EngineeringModelSetup"/>.
        /// </returns>
        public virtual CDP4Common.DTO.EngineeringModelSetup MapToDto(NpgsqlDataReader reader)
        {
            string tempModifiedOn;
            string tempName;
            string tempShortName;
            string tempKind;
            string tempStudyPhase;
            string tempEngineeringModelIid;
            string tempSourceEngineeringModelSetupIid;

            var valueDict      = (Dictionary <string, string>)reader["ValueTypeSet"];
            var iid            = Guid.Parse(reader["Iid"].ToString());
            var revisionNumber = int.Parse(valueDict["RevisionNumber"]);

            var dto = new CDP4Common.DTO.EngineeringModelSetup(iid, revisionNumber);

            dto.ExcludedPerson.AddRange(Array.ConvertAll((string[])reader["ExcludedPerson"], Guid.Parse));
            dto.ExcludedDomain.AddRange(Array.ConvertAll((string[])reader["ExcludedDomain"], Guid.Parse));
            dto.Alias.AddRange(Array.ConvertAll((string[])reader["Alias"], Guid.Parse));
            dto.Definition.AddRange(Array.ConvertAll((string[])reader["Definition"], Guid.Parse));
            dto.HyperLink.AddRange(Array.ConvertAll((string[])reader["HyperLink"], Guid.Parse));
            dto.Participant.AddRange(Array.ConvertAll((string[])reader["Participant"], Guid.Parse));
            dto.ActiveDomain.AddRange(Array.ConvertAll((string[])reader["ActiveDomain"], Guid.Parse));
            dto.RequiredRdl.AddRange(Array.ConvertAll((string[])reader["RequiredRdl"], Guid.Parse));
            dto.IterationSetup.AddRange(Array.ConvertAll((string[])reader["IterationSetup"], Guid.Parse));

            if (valueDict.TryGetValue("ModifiedOn", out tempModifiedOn))
            {
                dto.ModifiedOn = Utils.ParseUtcDate(tempModifiedOn);
            }

            if (valueDict.TryGetValue("Name", out tempName))
            {
                dto.Name = tempName.UnEscape();
            }

            if (valueDict.TryGetValue("ShortName", out tempShortName))
            {
                dto.ShortName = tempShortName.UnEscape();
            }

            if (valueDict.TryGetValue("Kind", out tempKind))
            {
                dto.Kind = Utils.ParseEnum <CDP4Common.SiteDirectoryData.EngineeringModelKind>(tempKind);
            }

            if (valueDict.TryGetValue("StudyPhase", out tempStudyPhase))
            {
                dto.StudyPhase = Utils.ParseEnum <CDP4Common.SiteDirectoryData.StudyPhaseKind>(tempStudyPhase);
            }

            if (valueDict.TryGetValue("EngineeringModelIid", out tempEngineeringModelIid))
            {
                dto.EngineeringModelIid = Guid.Parse(tempEngineeringModelIid);
            }

            if (valueDict.TryGetValue("SourceEngineeringModelSetupIid", out tempSourceEngineeringModelSetupIid) && tempSourceEngineeringModelSetupIid != null)
            {
                dto.SourceEngineeringModelSetupIid = Guid.Parse(tempSourceEngineeringModelSetupIid);
            }

            return(dto);
        }