Exemplo n.º 1
0
        /// <summary>
        /// Determine the engineering model setup based on the supplied routeSegments.
        /// </summary>
        /// <param name="processor">
        /// The processor instance.
        /// </param>
        /// <param name="routeSegments">
        /// The route segments constructed from the request path.
        /// </param>
        /// <returns>
        /// The resolved <see cref="EngineeringModelSetup"/>.
        /// </returns>
        /// <exception cref="Exception">
        /// If engineering model could not be resolved
        /// </exception>
        private EngineeringModelSetup DetermineEngineeringModelSetup(IProcessor processor, string[] routeSegments)
        {
            // override query parameters to return only extent shallow
            this.RequestUtils.OverrideQueryParameters = new QueryParameters();

            var securityContext = new RequestSecurityContext {
                ContainerReadAllowed = true
            };

            // set the transaction to default context to retrieve SiteDirectory data
            this.TransactionManager.SetDefaultContext(processor.Transaction);

            // take first segment and try to resolve the engineering model setup for further processing
            var siteDir                = (SiteDirectory)processor.GetResource("SiteDirectory", SiteDirectoryData, null, securityContext).Single();
            var requestedModelId       = Utils.ParseIdentifier(routeSegments[1]);
            var engineeringModelSetups = processor.GetResource("EngineeringModelSetup", SiteDirectoryData, siteDir.Model, securityContext);
            var modelSetups            = engineeringModelSetups.Where(x => ((EngineeringModelSetup)x).EngineeringModelIid == requestedModelId).ToList();

            if (modelSetups.Count != 1)
            {
                throw new Exception("Engineering model could not be resolved");
            }

            // override query parameters to return only extent shallow
            this.RequestUtils.OverrideQueryParameters = null;

            return((EngineeringModelSetup)modelSetups.Single());
        }
        /// <summary>
        /// Get all things from the fileStore.
        /// </summary>
        /// <param name="thing">
        /// The thing to get file data for.
        /// </param>
        /// <param name="routeSegments">
        /// The route segments.
        /// </param>
        /// <param name="partition">
        /// The database partition (schema) where the requested resource is stored.
        /// </param>
        /// <param name="transaction">
        /// The current transaction to the database.
        /// </param>
        /// <param name="authorizedContext">
        /// The security context of the container instance.
        /// </param>
        /// <returns>
        /// The list of things form a fileStore.
        /// </returns>
        private List <Thing> GetFileStoreThings(
            Thing thing,
            dynamic routeSegments,
            string partition,
            NpgsqlTransaction transaction,
            RequestSecurityContext authorizedContext)
        {
            var iids = new List <Guid>();

            if (routeSegments.Length == 8 && routeSegments[6] == "folder")
            {
                iids.Add(Guid.Parse(routeSegments[5]));
                return(this.DomainFileStoreService.GetDeep(transaction, partition, iids, authorizedContext).ToList());
            }

            if (routeSegments.Length == 6 && routeSegments[4] == "folder")
            {
                iids.Add(Guid.Parse(routeSegments[3]));
                return(this.CommonFileStoreService.GetDeep(transaction, partition, iids, authorizedContext).ToList());
            }

            if (routeSegments.Length == 6 && routeSegments[4] == "domainFileStore")
            {
                iids.Add(thing.Iid);
                return(this.DomainFileStoreService.GetDeep(transaction, partition, iids, authorizedContext).ToList());
            }

            if (routeSegments.Length == 4 && routeSegments[2] == "commonFileStore")
            {
                iids.Add(thing.Iid);
                return(this.CommonFileStoreService.GetDeep(transaction, partition, iids, authorizedContext).ToList());
            }

            return(new List <Thing>());
        }
        /// <summary>
        /// Gets the <see cref="CDP4Common.DTO.SiteReferenceDataLibrary"/> chain for each supplied <see cref="CDP4Common.DTO.ModelReferenceDataLibrary"/> guid
        /// </summary>
        /// <param name="requiredRdlGuid">
        /// The <see cref="Guid"/> of the <see cref="CDP4Common.DTO.SiteReferenceDataLibrary"/> to get the chain for
        /// </param>
        /// <param name="siteReferenceDataLibraries">
        /// The <see cref="CDP4Common.DTO.SiteReferenceDataLibrary"/> set where to store found <see cref="CDP4Common.DTO.SiteReferenceDataLibrary"/>
        /// </param>
        /// <param name="transaction">
        /// The current transaction to the database.
        /// </param>
        /// <param name="authorizedContext">
        /// The security context of the container instance.
        /// </param>
        /// <param name="partition">
        /// The database partition (schema) where the requested resource is stored.
        /// </param>
        private void GetSiteRdlChain(
            Guid requiredRdlGuid,
            HashSet <SiteReferenceDataLibrary> siteReferenceDataLibraries,
            NpgsqlTransaction transaction,
            RequestSecurityContext authorizedContext,
            string partition)
        {
            var requiredRdlGuidList = new List <Guid>();

            requiredRdlGuidList.Add(requiredRdlGuid);
            var requiredRdl = this.SiteReferenceDataLibraryService
                              .GetShallow(transaction, partition, requiredRdlGuidList, authorizedContext)
                              .OfType <SiteReferenceDataLibrary>().ToList()[0];

            siteReferenceDataLibraries.Add(requiredRdl);

            var nextRequiredRdlGuid = requiredRdl.RequiredRdl;

            if (nextRequiredRdlGuid != null)
            {
                this.GetSiteRdlChain(
                    (Guid)nextRequiredRdlGuid,
                    siteReferenceDataLibraries,
                    transaction,
                    authorizedContext,
                    partition);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Writes the <see cref="CDP4Common.DTO.ModelReferenceDataLibrary"/> to the <see cref="ZipFile"/>
        /// </summary>
        /// <param name="modelReferenceDataLibraries">
        /// The <see cref="CDP4Common.SiteDirectoryData.ModelReferenceDataLibrary"/> that are to be written to the <see cref="ZipFile"/>
        /// </param>
        /// <param name="zipFile">
        /// The target <see cref="ZipFile"/> that the <see cref="modelReferenceDataLibraries"/> are written to.
        /// </param>
        /// <param name="filePath">
        /// The file of the target <see cref="ZipFile"/>
        /// </param>
        /// <param name="transaction">
        /// The current transaction to the database.
        /// </param>
        /// <param name="authorizedContext">
        /// The security context of the container instance.
        /// </param>
        /// <param name="partition">
        /// The database partition (schema) where the requested resource is stored.
        /// </param>
        private void WriteModelReferenceDataLibraryToZipFile(
            IEnumerable <ModelReferenceDataLibrary> modelReferenceDataLibraries,
            ZipFile zipFile,
            string filePath,
            NpgsqlTransaction transaction,
            RequestSecurityContext authorizedContext,
            string partition)
        {
            // Force deep get for reference data libraries
            var queryParameters = new QueryParameters {
                IncludeReferenceData = true, ExtentDeep = true
            };

            this.RequestUtils.OverrideQueryParameters = queryParameters;

            foreach (var modelReferenceDataLibrary in modelReferenceDataLibraries)
            {
                // Get all modelRdl objects excluding modelRdl itself
                var dtos = this.ModelReferenceDataLibraryService
                           .GetDeep(
                    transaction,
                    partition,
                    new List <Guid> {
                    modelReferenceDataLibrary.Iid
                },
                    authorizedContext).ToList().Where(x => x.ClassKind != ClassKind.ModelReferenceDataLibrary);

                // Serialize and save dtos to the archive
                using (var memoryStream = new MemoryStream())
                {
                    this.JsonSerializer.SerializeToStream(dtos, memoryStream);
                    using (var outputStream = new MemoryStream(memoryStream.ToArray()))
                    {
                        var modelReferenceDataLibraryFilename = string.Format(
                            "{0}{1}{2}.json",
                            ModelRdlZipLocation,
                            Path.DirectorySeparatorChar,
                            modelReferenceDataLibrary.Iid);
                        var zipEntry = zipFile.AddEntry(modelReferenceDataLibraryFilename, outputStream);
                        zipEntry.Comment = string.Format(
                            "The {0} ModelReferenceDataLibrary",
                            modelReferenceDataLibrary.ShortName);
                        zipFile.Save(filePath);
                    }
                }
            }

            // Set query parameters back
            this.RequestUtils.OverrideQueryParameters = null;
        }
 /// <summary>
 /// Gets the <see cref="CDP4Common.DTO.SiteReferenceDataLibrary"/> for each supplied <see cref="CDP4Common.DTO.ModelReferenceDataLibrary"/>
 /// </summary>
 /// <param name="modelReferenceDataLibraries">
 /// The <see cref="CDP4Common.DTO.ModelReferenceDataLibrary"/> to get <see cref="CDP4Common.DTO.SiteReferenceDataLibrary"/> for
 /// </param>
 /// <param name="siteReferenceDataLibraries">
 /// The <see cref="CDP4Common.DTO.SiteReferenceDataLibrary"/> set where to store found <see cref="CDP4Common.DTO.SiteReferenceDataLibrary"/>
 /// </param>
 /// <param name="transaction">
 /// The current transaction to the database.
 /// </param>
 /// <param name="authorizedContext">
 /// The security context of the container instance.
 /// </param>
 /// <param name="partition">
 /// The database partition (schema) where the requested resource is stored.
 /// </param>
 private void GetSiteReferenceDataLibraries(
     List <ModelReferenceDataLibrary> modelReferenceDataLibraries,
     HashSet <SiteReferenceDataLibrary> siteReferenceDataLibraries,
     NpgsqlTransaction transaction,
     RequestSecurityContext authorizedContext,
     string partition)
 {
     foreach (var modelReferenceDataLibrary in modelReferenceDataLibraries)
     {
         var requiredRdlGuid = modelReferenceDataLibrary.RequiredRdl;
         if (requiredRdlGuid != null)
         {
             this.GetSiteRdlChain(
                 (Guid)requiredRdlGuid,
                 siteReferenceDataLibraries,
                 transaction,
                 authorizedContext,
                 partition);
         }
     }
 }
Exemplo n.º 6
0
        /// <summary>
        /// Determine the iteration based on the supplied routeSegments.
        /// </summary>
        /// <param name="processor">
        /// The processor instance.
        /// </param>
        /// <param name="partition">The partition of the search.</param>
        /// <param name="routeSegments">
        /// The route segments constructed from the request path.
        /// </param>
        /// <returns>
        /// The resolved <see cref="Iteration"/>.
        /// </returns>
        private Iteration DetermineIteration(IProcessor processor, string partition, string[] routeSegments)
        {
            if (routeSegments.Length >= 4 && routeSegments[2] == "iteration")
            {
                var securityContext = new RequestSecurityContext {
                    ContainerReadAllowed = true, Credentials = this.PermissionService.Credentials
                };

                var requestedIterationId = Utils.ParseIdentifier(routeSegments[3]);
                var iterations           = processor.GetResource("Iteration", partition, new List <Guid> {
                    requestedIterationId
                }, securityContext).ToList();

                if (iterations.Count != 1)
                {
                    throw new Exception("Iteration could not be resolved");
                }

                return((Iteration)iterations.Single());
            }

            return(null);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Gets the source data for the copy operation
        /// </summary>
        /// <param name="transaction">The current transaction</param>
        /// <param name="copyinfo">The <see cref="CopyInfo"/></param>
        /// <param name="requestPartition">The contextual partition</param>
        /// <returns>The source data</returns>
        public IReadOnlyList <Thing> GetCopySourceData(NpgsqlTransaction transaction, CopyInfo copyinfo, string requestPartition)
        {
            if (copyinfo.Source.IterationId.HasValue && copyinfo.Source.IterationId.Value != Guid.Empty)
            {
                var topcontainerPartition = $"EngineeringModel_{copyinfo.Source.TopContainer.Iid.ToString().Replace("-", "_")}";
                this.TransactionManager.SetIterationContext(transaction, topcontainerPartition, copyinfo.Source.IterationId.Value);
            }

            // transaction shall be contextual to source iteration if applicable (get new transaction)
            var partition = copyinfo.Source.IterationId.HasValue && copyinfo.Source.IterationId.Value != Guid.Empty
                ? $"Iteration_{copyinfo.Source.TopContainer.Iid.ToString().Replace("-", "_")}"
                : $"EngineeringModel_{copyinfo.Source.TopContainer.Iid.ToString().Replace("-", "_")}";

            var readservice = this.ServiceProvider.MapToReadService(copyinfo.Source.Thing.ClassKind.ToString());

            var securityContext = new RequestSecurityContext {
                ContainerReadAllowed = true, ContainerWriteAllowed = true
            };

            var sourceThings = copyinfo.Options.CopyKind == CopyKind.Deep
                ? readservice.GetDeep(transaction, partition, new[] { copyinfo.Source.Thing.Iid }, securityContext)
                : readservice.GetShallow(transaction, partition, new[] { copyinfo.Source.Thing.Iid }, securityContext);

            var source = sourceThings.ToList();

            // also get all referenced element-definition as they dont exist in target iteration
            if (copyinfo.Source.IterationId.Value != copyinfo.Target.IterationId.Value)
            {
                source.AddRange(this.GetElementDefinitionTreeFromRootDefinition(transaction, partition, securityContext, source, readservice, source.Select(x => x.Iid).ToList()));
            }

            // revert context to current
            this.TransactionManager.SetIterationContext(transaction, requestPartition, copyinfo.Target.IterationId.Value);

            return(source);
        }
        /// <summary>
        /// The create file structure on disk.
        /// </summary>
        /// <param name="thing">
        /// The thing to get file data for.
        /// </param>
        /// <param name="partition">
        /// The database partition (schema) where the requested resource is stored.
        /// </param>
        /// <param name="folderPath">
        /// The folder path where the structure will be created.
        /// </param>
        /// <param name="routeSegments">
        /// The route segments.
        /// </param>
        private void CreateFileStructureOnDisk(Thing thing, string partition, string folderPath, dynamic routeSegments)
        {
            var logMessage = string.Format(
                "File structure creation is started into the temporary folder {0}.",
                folderPath);

            Logger.Info(logMessage);

            var credentials       = this.Cdp4Context.Context.CurrentUser as Credentials;
            var authorizedContext = new RequestSecurityContext {
                ContainerReadAllowed = true
            };

            NpgsqlConnection  connection  = null;
            NpgsqlTransaction transaction = this.TransactionManager.SetupTransaction(ref connection, credentials);

            try
            {
                List <Thing> things = this.GetFileStoreThings(
                    thing,
                    routeSegments,
                    partition,
                    transaction,
                    authorizedContext);

                if (things.Any())
                {
                    // Get all folders
                    var folders = things.Where(i => i.GetType() == typeof(Folder)).Cast <Folder>().ToList();

                    // Get all files
                    var files = things.Where(i => i.GetType() == typeof(File))
                                .Cast <File>().ToList();

                    // Get all files
                    var fileRevisions = things.Where(i => i.GetType() == typeof(FileRevision)).Cast <FileRevision>()
                                        .ToList();

                    // Get all fileType iids
                    var fileTypeOrderedItems = new List <OrderedItem>();
                    foreach (var fileRevision in fileRevisions)
                    {
                        fileTypeOrderedItems.AddRange(fileRevision.FileType);
                    }

                    // Get fileTypes iids
                    var fileTypeIids = new List <Guid>();
                    foreach (var fileTypeOrderedItem in fileTypeOrderedItems)
                    {
                        fileTypeIids.Add(Guid.Parse(fileTypeOrderedItem.V.ToString()));
                    }

                    // Get all fileTypes
                    var fileTypes = this.FileTypeService
                                    .GetShallow(transaction, "SiteDirectory", fileTypeIids.Distinct(), authorizedContext)
                                    .OfType <FileType>().ToList();

                    if (thing.ClassKind != ClassKind.Folder)
                    {
                        // Get all root folders
                        var rootFolders = folders.Where(folder => folder.ContainingFolder == null);

                        // Iterate all root folders and find child folders and files for the file store
                        foreach (var rootFolder in rootFolders)
                        {
                            this.GetFoldersAndFiles(rootFolder, folders, files, fileRevisions, folderPath, fileTypes);
                        }

                        // Get root files
                        this.GetFiles(null, files, fileRevisions, folderPath, fileTypes);
                    }
                    else
                    {
                        // Find child folders and files for the folder
                        this.GetFoldersAndFiles(thing as Folder, folders, files, fileRevisions, folderPath, fileTypes);
                    }
                }

                transaction.Commit();
            }
            catch (Exception ex)
            {
                if (transaction != null && !transaction.IsCompleted)
                {
                    transaction.Rollback();
                }

                Logger.Error(ex, "Failed to create a file structure on the disk.");
            }
            finally
            {
                if (transaction != null)
                {
                    transaction.Dispose();
                }

                if (connection != null)
                {
                    connection.Dispose();
                }
            }
        }
        /// <summary>
        /// Writes the <see cref="CDP4Common.DTO.EngineeringModel"/> and its <see cref="CDP4Common.DTO.Iteration"/> to the <see cref="ZipFile"/>
        /// </summary>
        /// <param name="engineeringModelSetups">
        /// The <see cref="CDP4Common.DTO.EngineeringModelSetup"/> which <see cref="CDP4Common.DTO.EngineeringModel"/> and its <see cref="CDP4Common.DTO.Iteration"/> are to be written to the <see cref="ZipFile"/>
        /// </param>
        /// <param name="zipFile">
        /// The target <see cref="ZipFile"/> that the <see cref="CDP4Common.DTO.EngineeringModel"/> and its <see cref="CDP4Common.DTO.Iteration"/> are written to.
        /// </param>
        /// <param name="filePath">
        /// The file of the target <see cref="ZipFile"/>
        /// </param>
        /// <param name="transaction">
        /// The current transaction to the database.
        /// </param>
        /// <param name="authorizedContext">
        /// The security context of the container instance.
        /// </param>
        private void WriteModelsWithIterationsToZipFile(
            IEnumerable <EngineeringModelSetup> engineeringModelSetups,
            ZipFile zipFile,
            string filePath,
            NpgsqlTransaction transaction,
            RequestSecurityContext authorizedContext)
        {
            string pattern     = "-";
            string replacement = "_";
            Regex  rgx         = new Regex(pattern);

            // Get the state of the current credentials and the participant flag
            var credentials            = this.RequestUtils.Context.AuthenticatedCredentials;
            var currentParticipantFlag = credentials.IsParticipant;

            // As EngineeringModel data will be retrieved the participant flag needs to be set to true
            credentials.IsParticipant = true;

            foreach (var engineeringModelSetup in engineeringModelSetups)
            {
                var modelPartition = rgx.Replace(
                    "EngineeringModel_" + engineeringModelSetup.EngineeringModelIid,
                    replacement);

                // Get participant permissions as EngineeringModel data will be retrieved
                credentials.EngineeringModelSetup = engineeringModelSetup;
                this.PersonResolver.ResolveParticipantCredentials(transaction, credentials);
                this.PermissionService.Credentials = credentials;

                // Get all engineeringModel objects
                var engineeringModelDtos = this.EngineeringModelService.GetDeep(
                    transaction,
                    modelPartition,
                    new List <Guid> {
                    engineeringModelSetup.EngineeringModelIid
                },
                    authorizedContext).ToList();

                var fileRevisions = engineeringModelDtos.Where(x => x.ClassKind == ClassKind.FileRevision)
                                    .OfType <FileRevision>().ToList();

                // Serialize and save dtos to the archive
                using (var engineeringModelMemoryStream = new MemoryStream())
                {
                    this.JsonSerializer.SerializeToStream(engineeringModelDtos, engineeringModelMemoryStream);

                    using (var outputStream = new MemoryStream(engineeringModelMemoryStream.ToArray()))
                    {
                        var engineeringModelFilename = string.Format(
                            @"{0}\{1}\{1}.json",
                            EngineeringModelZipLocation,
                            engineeringModelSetup.EngineeringModelIid);
                        var engineeringModelZipEntry = zipFile.AddEntry(engineeringModelFilename, outputStream);
                        engineeringModelZipEntry.Comment = string.Format(
                            "The {0} EngineeringModel",
                            engineeringModelSetup.ShortName);
                        zipFile.Save(filePath);
                    }
                }

                var engineeringModel =
                    (EngineeringModel)engineeringModelDtos.Single(x => x.ClassKind == ClassKind.EngineeringModel);
                var iterationIids = engineeringModel.Iteration;

                foreach (var iterationIid in iterationIids)
                {
                    // Set the iteration context for transaction
                    this.TransactionManager.SetIterationContext(transaction, modelPartition, iterationIid);

                    // Get all iteration objects
                    var iterationDtos = this.IterationService.GetDeep(
                        transaction,
                        modelPartition,
                        new List <Guid> {
                        iterationIid
                    },
                        authorizedContext).ToList();

                    fileRevisions.AddRange(
                        iterationDtos.Where(x => x.ClassKind == ClassKind.FileRevision).OfType <FileRevision>()
                        .ToList());

                    // Serialize and save dtos to the archive
                    using (var iterationMemoryStream = new MemoryStream())
                    {
                        this.JsonSerializer.SerializeToStream(iterationDtos, iterationMemoryStream);

                        using (var outputStream = new MemoryStream(iterationMemoryStream.ToArray()))
                        {
                            var iterationFilename = string.Format(
                                @"{0}\{1}\{2}\{3}.json",
                                EngineeringModelZipLocation,
                                engineeringModelSetup.EngineeringModelIid,
                                IterationZipLocation,
                                iterationIid);
                            zipFile.AddEntry(iterationFilename, outputStream);
                            zipFile.Save(filePath);
                        }
                    }
                }

                // Add files to the archive
                foreach (var fileRevision in fileRevisions)
                {
                    var fileRevisionPath = string.Format(
                        @"{0}\{1}\{2}",
                        EngineeringModelZipLocation,
                        engineeringModelSetup.EngineeringModelIid,
                        FileRevisionZipLocation);

                    string storageFilePath;
                    this.FileBinaryService.TryGetFileStoragePath(fileRevision.ContentHash, out storageFilePath);

                    zipFile.AddFile(storageFilePath, fileRevisionPath);
                    zipFile.Save(filePath);
                }
            }

            // Set the state of the credentials and the participant flag before retrieving EngineeringModel data
            credentials.IsParticipant          = currentParticipantFlag;
            this.PermissionService.Credentials = credentials;
        }
        /// <summary>
        /// Factory method that creates a <see cref="ExchangeFileHeader"/> based on the provided <see cref="person"/>
        /// </summary>
        /// <param name="person">
        /// The <see cref="Person"/> that is used to create the <see cref="ExchangeFileHeader"/>
        /// </param>
        /// <param name="transaction">
        /// The current transaction to the database.
        /// </param>
        /// <param name="authorizedContext">
        /// The security context of the container instance.
        /// </param>
        /// <param name="partition">
        /// The database partition (schema) where the requested resource is stored.
        /// </param>
        /// <returns>
        /// An instance of <see cref="ExchangeFileHeader"/>
        /// </returns>
        private ExchangeFileHeader CreateExchangeFileHeader(
            Person person,
            NpgsqlTransaction transaction,
            RequestSecurityContext authorizedContext,
            string partition)
        {
            EmailAddress email = null;

            if (person.DefaultEmailAddress != null)
            {
                email = this.EmailAddressService.GetShallow(
                    transaction,
                    partition,
                    new List <Guid> {
                    (Guid)person.DefaultEmailAddress
                },
                    authorizedContext).OfType <EmailAddress>().ToList()[0];
            }

            var exchangeFileInitiator =
                new ExchangeFileInitiator
            {
                Iid       = person.Iid,
                GivenName = person.GivenName,
                Surname   = person.Surname,
                Email     = email != null ? email.Value : string.Empty
            };

            Organization organizationDto = null;

            if (person.Organization != null)
            {
                organizationDto = this.OrganizationService
                                  .GetShallow(transaction, partition, new List <Guid> {
                    (Guid)person.Organization
                }, authorizedContext)
                                  .OfType <Organization>().ToList()[0];
            }

            var organization = organizationDto != null
                                   ? new OrganizationInfo
            {
                Iid  = organizationDto.Iid,
                Name = organizationDto.Name,
                Site = null,
                Unit = !string.IsNullOrEmpty(person.OrganizationalUnit)
                                                        ? person.OrganizationalUnit
                                                        : null
            }
                                   : null;

            var exchangeFileHeader =
                new ExchangeFileHeader
            {
                DataModelVersion    = "2.4.1",
                Remark              = ExchangeHeaderRemark,
                Copyright           = ExchangeHeaderCopyright,
                Extensions          = null,
                CreatorPerson       = exchangeFileInitiator,
                CreatorOrganization = organization
            };

            return(exchangeFileHeader);
        }
        /// <summary>
        /// Creates a  <see cref="IEnumerable{Thing}"/> that contains references to those objects that are to be included
        /// in the JSON file
        /// </summary>
        /// <param name="siteDirectory">
        /// The <see cref="SiteDirectory"/> object that is to be serialized to the JSON file
        /// </param>
        /// <param name="siteReferenceDataLibraries">
        /// The <see cref="SiteReferenceDataLibrary"/> instances that are to be included
        /// </param>
        /// <param name="domainOfExpertises">
        /// The <see cref="DomainOfExpertise"/> instances that are to be included
        /// </param>
        /// <param name="persons">
        /// /// The <see cref="Person"/> instances that are to be included
        /// </param>
        /// <param name="engineeringModelSetups">
        /// The engineering Model Setups.
        /// </param>
        /// <param name="transaction">
        /// The current transaction to the database.
        /// </param>
        /// <param name="authorizedContext">
        /// The security context of the container instance.
        /// </param>
        /// <param name="partition">
        /// The database partition (schema) where the requested resource is stored.
        /// </param>
        /// <returns>
        /// The pruned <see cref="Thing"/> collection.
        /// </returns>
        private IEnumerable <Thing> CreateSiteDirectoryAndPrunedContainedThingDtos(
            SiteDirectory siteDirectory,
            HashSet <SiteReferenceDataLibrary> siteReferenceDataLibraries,
            IEnumerable <DomainOfExpertise> domainOfExpertises,
            HashSet <Person> persons,
            IEnumerable <EngineeringModelSetup> engineeringModelSetups,
            NpgsqlTransaction transaction,
            RequestSecurityContext authorizedContext,
            string partition)
        {
            var dtos = new List <Thing>();

            var siteDirectoryItems = this.SiteDirectoryService.GetDeep(
                transaction,
                partition,
                new List <Guid> {
                siteDirectory.Iid
            },
                authorizedContext);

            SiteDirectory siteDirectoryDto = siteDirectory.DeepClone <SiteDirectory>();

            dtos.Add(siteDirectoryDto);

            // collect the SiteDirectory object graph, except for the graph branches that need to be pruned
            foreach (var siteDirectoryItem in siteDirectoryItems)
            {
                if (siteDirectoryItem.ClassKind != ClassKind.SiteDirectory &&
                    siteDirectoryItem.ClassKind != ClassKind.SiteReferenceDataLibrary &&
                    siteDirectoryItem.ClassKind != ClassKind.DomainOfExpertise &&
                    siteDirectoryItem.ClassKind != ClassKind.Person &&
                    siteDirectoryItem.ClassKind != ClassKind.EngineeringModelSetup)
                {
                    var containerClassNameList = this.GetContainerClassNameList(siteDirectoryItem);
                    var exclude = this.CheckClassNameForExclusion(containerClassNameList);

                    if (!exclude)
                    {
                        dtos.Add(siteDirectoryItem);
                    }
                }
            }

            // remove the domains-of-expertise that should not be included in the cloned SiteDirectory
            siteDirectoryDto.Domain.Clear();
            foreach (var domainOfExpertise in domainOfExpertises)
            {
                var domainOfExpertiseDtos = this.DomainOfExpertiseService.GetDeep(
                    transaction,
                    partition,
                    new List <Guid> {
                    domainOfExpertise.Iid
                },
                    authorizedContext);
                dtos.AddRange(domainOfExpertiseDtos);

                siteDirectoryDto.Domain.Add(domainOfExpertise.Iid);
            }

            // remove the persons that should not be included in SiteDirectory DTO from the DTO
            siteDirectoryDto.Person.Clear();
            foreach (var person in persons)
            {
                var personDtos = this.PersonService.GetDeep(
                    transaction,
                    partition,
                    new List <Guid> {
                    person.Iid
                },
                    authorizedContext);
                dtos.AddRange(personDtos);
                siteDirectoryDto.Person.Add(person.Iid);
            }

            // remove the EngineeringModelSetup instances and replace with only required ones
            siteDirectoryDto.Model.Clear();
            foreach (var engineeringModelSetup in engineeringModelSetups)
            {
                // retrieve the EngineeringModelSetup contained object graph, including a shallow copy of the ModelReferenceDataLibrary
                // the ModelReferenceDataLibrary contained objects are written to its respective JSON file
                var engineeringModelSetupDtos = this.EngineeringModelSetupService.GetDeep(
                    transaction,
                    partition,
                    new List <Guid> {
                    engineeringModelSetup.Iid
                },
                    authorizedContext);
                dtos.AddRange(engineeringModelSetupDtos);

                siteDirectoryDto.Model.Add(engineeringModelSetup.Iid);
            }

            // remove the SiteReferenceDataLibrary instances and replace with only referenced ones
            siteDirectoryDto.SiteReferenceDataLibrary.Clear();
            foreach (var siteReferenceDataLibrary in siteReferenceDataLibraries)
            {
                dtos.Add(siteReferenceDataLibrary);

                siteDirectoryDto.SiteReferenceDataLibrary.Add(siteReferenceDataLibrary.Iid);
            }

            // Clean the list from duplicates (for instance Definition)
            return(dtos.DistinctBy(x => x.Iid));
        }
        /// <summary>
        /// Create a zip export file with EngineeringModels from supplied EngineeringModelSetupGuids and paths to files.
        /// </summary>
        /// <param name="engineeringModelSetupGuids">
        /// The provided list of <see cref="Guid"/> of EngineeringModelSetups to write to the zip file
        /// </param>
        /// <param name="files">
        /// The path to the files that need to be uploaded. If <paramref name="files"/> is null, then no files are to be uploaded
        /// </param>
        /// <returns>
        /// The <see cref="string"/> path of the created archive.
        /// </returns>
        public string CreateZipExportFile(
            IEnumerable <Guid> engineeringModelSetupGuids,
            IEnumerable <string> files = null)
        {
            // Initialize the json serializer
            this.JsonSerializer.Initialize(
                this.RequestUtils.MetaInfoProvider,
                this.RequestUtils.GetRequestDataModelVersion);

            var siteReferenceDataLibraries = new HashSet <SiteReferenceDataLibrary>();
            var credentials       = this.Cdp4Context.Context.CurrentUser as Credentials;
            var authorizedContext = new RequestSecurityContext {
                ContainerReadAllowed = true
            };

            NpgsqlConnection  connection  = null;
            NpgsqlTransaction transaction = this.TransactionManager.SetupTransaction(ref connection, credentials);

            try
            {
                var siteDirectoryPartition = "SiteDirectory";

                SiteDirectory siteDirectory = this.SiteDirectoryService
                                              .GetShallow(transaction, siteDirectoryPartition, null, authorizedContext).OfType <SiteDirectory>()
                                              .ToList()[0];

                var engineeringModelSetupThings = this.EngineeringModelSetupService.GetDeep(
                    transaction,
                    siteDirectoryPartition,
                    engineeringModelSetupGuids,
                    authorizedContext).ToList();

                // Get required EngineeringModelSetups
                var engineeringModelSetups = engineeringModelSetupThings
                                             .Where(x => x.ClassKind == ClassKind.EngineeringModelSetup).OfType <EngineeringModelSetup>()
                                             .ToList();

                // Get all DomainOfExpertises that are contained by the EngineeringModelSetups
                List <DomainOfExpertise> domainsOfExpertises = new List <DomainOfExpertise>();
                foreach (var engineeringModelSetup in engineeringModelSetups)
                {
                    var activeDomains = this.DomainOfExpertiseService
                                        .GetShallow(
                        transaction,
                        siteDirectoryPartition,
                        engineeringModelSetup.ActiveDomain,
                        authorizedContext).OfType <DomainOfExpertise>().ToList();
                    domainsOfExpertises.AddRange(activeDomains);
                }

                // Get all ModelReferenceDataLibraris that are contained by the EngineeringModelSetups
                var modelReferenceDataLibraries = engineeringModelSetupThings
                                                  .Where(x => x.ClassKind == ClassKind.ModelReferenceDataLibrary).OfType <ModelReferenceDataLibrary>()
                                                  .ToList();

                // Get all Persons that are contained by the EngineeringModelSetups
                var siteDirectoryPersons = this.PersonService
                                           .GetShallow(transaction, siteDirectoryPartition, null, authorizedContext).OfType <Person>().ToList();
                var participants = engineeringModelSetupThings.Where(x => x.ClassKind == ClassKind.Participant)
                                   .OfType <Participant>().ToList();
                var persons = this.GetPersonsFromParticipants(siteDirectoryPersons, participants);

                // Get all unique SiteReferenceDataLibraries that are referenced by ModelReferenceDataLibraries
                this.GetSiteReferenceDataLibraries(
                    modelReferenceDataLibraries,
                    siteReferenceDataLibraries,
                    transaction,
                    authorizedContext,
                    siteDirectoryPartition);

                var prunedSiteDirectoryDtos = this.CreateSiteDirectoryAndPrunedContainedThingDtos(
                    siteDirectory,
                    siteReferenceDataLibraries,
                    domainsOfExpertises,
                    persons,
                    engineeringModelSetups,
                    transaction,
                    authorizedContext,
                    siteDirectoryPartition);

                var activePersonGuidList = new List <Guid> {
                    this.Cdp4Context.AuthenticatedCredentials.Person.Iid
                };

                var activePerson = this.PersonService
                                   .GetShallow(transaction, siteDirectoryPartition, activePersonGuidList, authorizedContext)
                                   .OfType <Person>().ToList()[0];

                var exchangeFileHeader = this.CreateExchangeFileHeader(
                    activePerson,
                    transaction,
                    authorizedContext,
                    siteDirectoryPartition);

                // Specify a random name for an archive.
                string path = Guid.NewGuid() + ".zip";

                try
                {
                    using (var zipFile = new ZipFile())
                    {
                        this.WriteHeaderToZipFile(exchangeFileHeader, zipFile, path);

                        this.WriteSiteDirectoryToZipFile(prunedSiteDirectoryDtos, zipFile, path);

                        this.WriteSiteReferenceDataLibraryToZipFile(
                            siteReferenceDataLibraries,
                            zipFile,
                            path,
                            transaction,
                            authorizedContext,
                            siteDirectoryPartition);

                        this.WriteModelReferenceDataLibraryToZipFile(
                            modelReferenceDataLibraries,
                            zipFile,
                            path,
                            transaction,
                            authorizedContext,
                            siteDirectoryPartition);

                        this.WriteModelsWithIterationsToZipFile(
                            engineeringModelSetups,
                            zipFile,
                            path,
                            transaction,
                            authorizedContext);
                    }

                    Logger.Info("Successfully exported selected models to {0}.", path);
                }
                catch (Exception ex)
                {
                    Logger.Error("Failed to export the open session to {0}. Error: {1}", path, ex.Message);

                    System.IO.File.Delete(path);
                }

                transaction.Commit();

                return(path);
            }
            catch (Exception ex)
            {
                if (transaction != null)
                {
                    transaction.Rollback();
                }

                Logger.Error("Failed to export the open session. Error: {0}", ex.Message);

                return(string.Empty);
            }
            finally
            {
                if (transaction != null)
                {
                    transaction.Dispose();
                }

                if (connection != null)
                {
                    connection.Dispose();
                }
            }
        }
        /// <summary>
        /// Process the get request and return the requested resources.
        /// </summary>
        /// <param name="processor">
        /// The resource accessor
        /// </param>
        /// <param name="topContainer">
        /// The top container.
        /// </param>
        /// <param name="partition">
        /// The data partition.
        /// </param>
        /// <param name="routeSegments">
        /// The route segments.
        /// </param>
        /// <param name="resourcePath">
        /// The resource Path.
        /// </param>
        /// <returns>
        /// The collection of retrieved <see cref="CDP4Common.DTO.Thing"/>.
        /// </returns>
        public IEnumerable <Thing> ProcessRequestPath(
            IProcessor processor,
            string topContainer,
            string partition,
            string[] routeSegments,
            out List <Thing> resourcePath)
        {
            var containmentColl   = new List <Thing>();
            var responseColl      = new List <Thing>();
            var authorizedContext = new RequestSecurityContext {
                ContainerReadAllowed = true
            };

            resourcePath = new List <Thing>();

            // select per route segment tuple (type and optional id)
            // processing containment from top to bottom, we populate first the containmentColl then the responseColl
            for (var i = 0; i < routeSegments.Length; i++)
            {
                if (i % 2 != 0)
                {
                    // iterate per tuple
                    continue;
                }

                // a resource containment path segment consists of a containment property name and identifier segment
                // it is preceded by the url host and is followed by the resource request
                var resourceContainmentSegment = routeSegments.Length > i + 2;

                // a general resource request path ends without any identifier segment or a wildcard character '*'
                var generalResourceRequest = (routeSegments.Length == i + 2 && routeSegments[i + 1] == "*") ||
                                             routeSegments.Length == i + 1;

                // a specific resource request path ends with an identifier segment
                var specificResourceRequest = !generalResourceRequest && routeSegments.Length == i + 2;

                var containerProperty = routeSegments[i];
                var serviceType       = i == 0
                                      ? topContainer
                                      : processor.GetContainmentType(containmentColl, containerProperty);

                if (serviceType == typeof(Iteration).Name && !generalResourceRequest)
                {
                    // switch to iteration context for further processing,
                    // in case of Iteration generalResource request, this is handled separately below
                    this.TransactionManager.SetIterationContext(processor.Transaction, partition);
                }

                if (resourceContainmentSegment)
                {
                    // this part is always used except for the last tuple
                    var identifier = Utils.ParseIdentifier(routeSegments[i + 1]);

                    processor.ValidateContainment(containmentColl, containerProperty, identifier);

                    var container =
                        processor.GetContainmentResource(serviceType, partition, identifier, authorizedContext);

                    if (serviceType == typeof(Iteration).Name)
                    {
                        // switch the partition (schema) for further processing, allowing retrieval of Iteration contained data
                        partition = partition.Replace("EngineeringModel", "Iteration");
                    }

                    // collect the specified containment resource
                    containmentColl.Add(container);
                    resourcePath.Add(container);

                    // authorized
                    authorizedContext.ContainerReadAllowed = true;
                }
                else if (generalResourceRequest)
                {
                    // get containment info
                    var containmentInfo = processor.GetContainment(containmentColl, containerProperty);

                    if (serviceType == typeof(Iteration).Name && containmentInfo != null)
                    {
                        // support temporal retrieval if iteration general resource is requested
                        // should only contain 1 element
                        foreach (var containedIterationId in containmentInfo)
                        {
                            // switch to iteration context for further processing
                            // use engineering-model id to set the iteration context
                            // partition here should be EngineeringModel_<uuid>
                            this.TransactionManager.SetIterationContext(
                                processor.Transaction,
                                partition,
                                containedIterationId);

                            // collect resources
                            responseColl.AddRange(
                                processor.GetResource(
                                    serviceType,
                                    partition,
                                    new[] { containedIterationId },
                                    authorizedContext));
                        }
                    }
                    else
                    {
                        // collect resources
                        responseColl.AddRange(
                            processor.GetResource(serviceType, partition, containmentInfo, authorizedContext));
                    }
                }
                else if (specificResourceRequest)
                {
                    var identifier = Utils.ParseIdentifier(routeSegments[i + 1]);

                    processor.ValidateContainment(containmentColl, containerProperty, identifier);

                    var resource = processor.GetResource(
                        serviceType,
                        partition,
                        new[] { identifier },
                        authorizedContext).ToList();
                    if (!resource.Any())
                    {
                        continue;
                    }

                    // collect resources
                    responseColl.AddRange(resource);

                    // set specific resource from uri request
                    resourcePath.Add(resource.First());
                }
            }

            if (this.RequestUtils.QueryParameters.IncludeAllContainers)
            {
                responseColl.InsertRange(0, containmentColl);
            }

            return(responseColl);
        }