/// <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); } }
/// <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); } } }
/// <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); }
/// <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); }