/// <summary> /// Read a list of <see cref="Thing"/>s in the associated <see cref="IDal"/> /// </summary> /// <param name="things">The <see cref="IEnumerable{Thing}"/> that contains the <see cref="Thing"/> to read</param> /// <param name="queryAttributes">The <see cref="IQueryAttributes"/> to be used to read data</param> /// <returns> /// an await-able <see cref="Task"/> /// </returns> public async Task Read(IEnumerable <Thing> things, IQueryAttributes queryAttributes) { if (this.ActivePerson == null) { throw new InvalidOperationException("The data cannot be read when the ActivePerson is null; The Open method must be called prior to any of the Read methods"); } var thingList = things.ToList(); if (!thingList.Any()) { throw new ArgumentException("The requested list of things is null or empty."); } logger.Info("Session.Read {0} things", thingList.Count()); var foundThings = new List <CDP4Common.DTO.Thing>(); // Create the token source var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenKey = Guid.NewGuid(); this.cancellationTokenSourceDictionary.TryAdd(cancellationTokenKey, cancellationTokenSource); try { // Max 10 async calls at a time, otherwise we could create a sort of a DDOS attack to the DAL/webservice var loopCount = 10; while (thingList.Any()) { var tasks = new List <Task <IEnumerable <CDP4Common.DTO.Thing> > >(); foreach (var thing in thingList.Take(loopCount)) { tasks.Add(this.Dal.Read(thing.ToDto(), cancellationTokenSource.Token, queryAttributes)); } var newThings = (await Task.WhenAll(tasks.ToArray())).SelectMany(x => x).ToList(); foundThings.AddRange(newThings); thingList = thingList.Skip(loopCount).ToList(); } } catch (OperationCanceledException) { logger.Info("Session.Read cancelled"); return; } finally { this.cancellationTokenSourceDictionary.TryRemove(cancellationTokenKey, out cancellationTokenSource); } await this.AfterReadOrWriteOrUpdate(foundThings); }
/// <summary> /// Read a <see cref="Thing"/> in the associated <see cref="IDal"/> /// </summary> /// <param name="thing">The <see cref="Thing"/> to read</param> /// <param name="queryAttributes">The <see cref="IQueryAttributes"/> to be used to read data</param> /// <returns> /// an await-able <see cref="Task"/> /// </returns> public async Task Read(Thing thing, IQueryAttributes queryAttributes) { if (this.ActivePerson == null) { throw new InvalidOperationException($"The {thing.ClassKind} cannot be read when the ActivePerson is null; The Open method must be called prior to any of the Read methods"); } logger.Info("Session.Read {0} {1}", thing.ClassKind, thing.Iid); var dto = thing.ToDto(); // Create the token source var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenKey = Guid.NewGuid(); this.cancellationTokenSourceDictionary.TryAdd(cancellationTokenKey, cancellationTokenSource); IEnumerable <CDP4Common.DTO.Thing> dtoThings; try { dtoThings = await this.Dal.Read(dto, cancellationTokenSource.Token, queryAttributes); } catch (OperationCanceledException) { logger.Info("Session.Read {0} {1} cancelled", thing.ClassKind, thing.Iid); return; } finally { this.cancellationTokenSourceDictionary.TryRemove(cancellationTokenKey, out cancellationTokenSource); } // proceed if no problem var enumerable = dtoThings as IList <CDP4Common.DTO.Thing> ?? dtoThings.ToList(); await this.AfterReadOrWriteOrUpdate(enumerable); }
public override Task <IEnumerable <Thing> > Read(Iteration iteration, CancellationToken cancellationToken, IQueryAttributes attributes = null) { throw new NotImplementedException(); }
public override Task <IEnumerable <Thing> > Read <T>(T thing, CancellationToken token, IQueryAttributes attributes = null) { throw new System.NotImplementedException(); }
/// <summary> /// Reads the data related to the provided <see cref="Thing"/> from the data-source /// </summary> /// <typeparam name="T"> /// an type of <see cref="Thing"/> /// </typeparam> /// <param name="thing"> /// An instance of <see cref="Thing"/> that needs to be read from the data-source /// </param> /// <param name="cancellationToken"> /// The <see cref="CancellationToken"/> /// </param> /// <param name="attributes"> /// An instance of <see cref="IQueryAttributes"/> to be passed along with the request /// </param> /// <returns> /// a list of <see cref="Thing"/> that are contained by the provided <see cref="Thing"/> including the <see cref="Thing"/> itself /// </returns> public override async Task <IEnumerable <Thing> > Read <T>(T thing, CancellationToken cancellationToken, IQueryAttributes attributes = null) { if (this.Credentials == null || this.Credentials.Uri == null) { throw new InvalidOperationException("The CDP4 DAL is not open."); } if (thing == null) { throw new ArgumentNullException(nameof(thing), $"The {nameof(thing)} may not be null"); } var watch = Stopwatch.StartNew(); if (attributes == null) { var includeReferenData = thing is ReferenceDataLibrary; attributes = this.GetIUriQueryAttribute(includeReferenData); } var thingRoute = this.CleanUriFinalSlash(thing.Route); var resourcePath = $"{thingRoute}{attributes?.ToString()}"; var readToken = CDP4Common.Helpers.TokenGenerator.GenerateRandomToken(); var uriBuilder = this.GetUriBuilder(this.Credentials.Uri, ref resourcePath); Logger.Debug("Resource Path {0}: {1}", readToken, resourcePath); Logger.Debug("CDP4Services GET {0}: {1}", readToken, uriBuilder); var requestsw = Stopwatch.StartNew(); var requestMessage = new HttpRequestMessage(HttpMethod.Get, resourcePath); requestMessage.Headers.Add(Headers.CDPToken, readToken); using (var httpResponseMessage = await this.httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken)) { Logger.Info("CDP4 Services responded in {0} [ms] to GET {1}", requestsw.ElapsedMilliseconds, readToken); requestsw.Stop(); if (httpResponseMessage.StatusCode != HttpStatusCode.OK) { var msg = $"The data-source replied with code {httpResponseMessage.StatusCode}: {httpResponseMessage.ReasonPhrase}"; Logger.Error(msg); throw new DalReadException(msg); } this.ProcessHeaders(httpResponseMessage); using (var resultStream = await httpResponseMessage.Content.ReadAsStreamAsync()) { var returned = this.Serializer.Deserialize(resultStream); if (this.TryExtractIterationIdfromUri(httpResponseMessage.RequestMessage.RequestUri, out var iterationId)) { this.SetIterationContainer(returned, iterationId); } watch.Stop(); Logger.Info("JSON Deserializer completed in {0} [ms]", watch.ElapsedMilliseconds); return(returned); } } }
/// <summary> /// Reads the data related to the provided <see cref="CDP4Common.EngineeringModelData.Iteration"/> from the data-source /// </summary> /// <param name="iteration"> /// An instance of <see cref="CDP4Common.EngineeringModelData.Iteration"/> that needs to be read from the data-source /// </param> /// <param name="cancellationToken"> /// The <see cref="CancellationToken"/> /// </param> /// <param name="attributes"> /// An instance of <see cref="IQueryAttributes"/> to be used with the request /// </param> /// <returns> /// A list of <see cref="Thing"/> that are contained by the provided <see cref="CDP4Common.EngineeringModelData.EngineeringModel"/> including the Reference-Data. /// All the <see cref="Thing"/>s that have been updated since the last read will be returned. /// </returns> /// <exception cref="InvalidOperationException"> /// Thrown when the <see cref="Session"/> property has not been set /// </exception> public override async Task <IEnumerable <Thing> > Read(CDP4Common.DTO.Iteration iteration, CancellationToken cancellationToken, IQueryAttributes attributes = null) { if (this.Session == null) { throw new InvalidOperationException("The Session may not be null and must be set prior to reading an Iteration"); } // Get the RequiredRdl to load var siteDirectory = this.Session.Assembler.RetrieveSiteDirectory(); var iterationSetup = siteDirectory.Model.SelectMany(mod => mod.IterationSetup).SingleOrDefault(it => it.IterationIid == iteration.Iid); if (iterationSetup == null) { throw new InvalidOperationException("The Iteration to open does not have any associated IterationSetup."); } var modelSetup = (EngineeringModelSetup)iterationSetup.Container; var modelReferenceDataLibrary = modelSetup.RequiredRdl.SingleOrDefault(); if (modelReferenceDataLibrary == null) { throw new InvalidOperationException("The model to open does not have a Required Reference-Data-Library."); } var modelReferenceDataLibraryDto = modelReferenceDataLibrary.ToDto(); var result = new List <Thing>(); var referenceData = await this.Read(modelReferenceDataLibraryDto, cancellationToken); result.AddRange(referenceData); var engineeringModelData = await this.Read((Thing)iteration, cancellationToken); result.AddRange(engineeringModelData); return(result); }
/// <summary> /// Reads the data related to the provided <see cref="Thing"/> from the data-source /// </summary> /// <typeparam name="T"> /// an type of <see cref="Thing"/> /// </typeparam> /// <param name="thing"> /// An instance of <see cref="Thing"/> that needs to be read from the data-source /// </param> /// <param name="cancellationToken"> /// The <see cref="CancellationToken"/> /// </param> /// <param name="attributes"> /// An instance of <see cref="IQueryAttributes"/> to be used with the request /// </param> /// <returns> /// A list of <see cref="Thing"/> that are contained by the provided <see cref="Thing"/> including the <see cref="Thing"/>. /// In case the /// <param name="thing"> /// </param> /// is a top container then all the <see cref="Thing"/>s that have been updated since the /// last read will be returned. /// </returns> public Task <IEnumerable <Thing> > Read <T>(T thing, CancellationToken cancellationToken, IQueryAttributes attributes = null) where T : Thing { throw new NotImplementedException(); }
/// <summary> /// Reads the data related to the provided <see cref="CDP4Common.EngineeringModelData.Iteration"/> from the data-source /// </summary> /// <param name="iteration"> /// An instance of <see cref="CDP4Common.EngineeringModelData.Iteration"/> that needs to be read from the data-source /// </param> /// <param name="cancellationToken"> /// The <see cref="CancellationToken"/> /// </param> /// <param name="attributes"> /// An instance of <see cref="IQueryAttributes"/> to be used with the request /// </param> /// <returns> /// A list of <see cref="Thing"/> that are contained by the provided <see cref="CDP4Common.EngineeringModelData.EngineeringModel"/> including the Reference-Data. /// All the <see cref="Thing"/>s that have been updated since the last read will be returned. /// </returns> public override async Task <IEnumerable <Thing> > Read(CDP4Common.DTO.Iteration iteration, CancellationToken cancellationToken, IQueryAttributes attributes = null) { return(await this.Read((Thing)iteration, cancellationToken, attributes)); }
/// <summary> /// Reads the data related to the provided <see cref="CDP4Common.DTO.Thing"/> from the data-source /// </summary> /// <typeparam name="T"> /// an type of <see cref="CDP4Common.DTO.Thing"/> /// </typeparam> /// <param name="thing"> /// An instance of <see cref="CDP4Common.DTO.Thing"/> that needs to be read from the data-source /// </param> /// <param name="cancellationToken"> /// The cancellation Token. /// </param> /// <param name="attributes"> /// An instance of <see cref="IQueryAttributes"/> to be passed along with the uri /// </param> /// <returns> /// a list of <see cref="CDP4Common.DTO.Thing"/> that are contained by the provided <see cref="CDP4Common.DTO.Thing"/> including the <see cref="CDP4Common.DTO.Thing"/> itself /// </returns> /// <exception cref="NotSupportedException"> /// Throws a <see cref="NotSupportedException"/> if the supplied T thing is not an <see cref="CDP4Common.DTO.Iteration"/>. /// </exception> public override async Task <IEnumerable <Thing> > Read <T>(T thing, CancellationToken cancellationToken, IQueryAttributes attributes = null) { // only read Iterations, domains or site reference data libraries in a file Dal if (!(thing is CDP4Common.DTO.Iteration) && !(thing is CDP4Common.DTO.SiteReferenceDataLibrary) && !(thing is CDP4Common.DTO.DomainOfExpertise)) { throw new NotSupportedException("The JSONFileDal only supports Read on Iteration, SiteReferenceDataLibrary and DomainOfExpertise instances."); } if (this.Credentials.Uri == null) { throw new ArgumentNullException(nameof(this.Credentials.Uri), $"The Credentials URI may not be null"); } // make sure that the uri is of the correct format UriExtensions.AssertUriIsFileSchema(this.Credentials.Uri); var filePath = this.Credentials.Uri.LocalPath; if (!System.IO.File.Exists(filePath)) { throw new FileNotFoundException($"The specified filepath does not exist or you do not have access to it: {filePath}"); } try { // re-read the to extract the reference data libraries that have not yet been fully dereferenced // and that are part of the required RDL's var siteDirectoryData = this.ReadSiteDirectoryJson(filePath, this.Credentials).ToList(); // read file, SiteDirectory first. using (var zip = ZipFile.Read(filePath)) { // get all relevant info from the selected iteration var siteDir = this.Session.RetrieveSiteDirectory(); var returned = new List <Thing>(); switch (thing.ClassKind) { case ClassKind.Iteration: returned = this.RetrieveIterationThings(thing as CDP4Common.DTO.Iteration, siteDirectoryData, zip, siteDir); break; case ClassKind.SiteReferenceDataLibrary: returned = this.RetrieveSRDLThings(thing as CDP4Common.DTO.SiteReferenceDataLibrary, siteDirectoryData, zip, siteDir); break; case ClassKind.DomainOfExpertise: returned = this.RetrieveDomainOfExpertiseThings(thing as CDP4Common.DTO.DomainOfExpertise, siteDirectoryData, siteDir); break; } return(returned); } } catch (Exception ex) { var msg = $"Failed to load file. Error: {ex.Message}"; Logger.Error(msg); if (this.Credentials != null) { this.Close(); } throw new FileLoadException(msg); } }
/// <summary> /// Reads the data related to the provided <see cref="CDP4Common.DTO.Iteration"/> from the data-source /// </summary> /// <param name="iteration"> /// An instance of <see cref="CDP4Common.DTO.Iteration"/> that needs to be read from the data-source /// </param> /// <param name="cancellationToken"> /// The <see cref="CancellationToken"/> /// </param> /// <param name="attributes"> /// An instance of <see cref="IQueryAttributes"/> to be used with the request /// </param> /// <returns> /// A list of <see cref="Thing"/> that are contained by the provided <see cref="CDP4Common.DTO.EngineeringModel"/> including the Reference-Data. /// All the <see cref="Thing"/>s that have been updated since the last read will be returned. /// </returns> public abstract Task <IEnumerable <Thing> > Read(Iteration iteration, CancellationToken cancellationToken, IQueryAttributes attributes = null);
/// <summary> /// Reads the data related to the provided <see cref="Thing"/> from the data-source /// </summary> /// <typeparam name="T"> /// an type of <see cref="Thing"/> /// </typeparam> /// <param name="thing"> /// An instance of <see cref="Thing"/> that needs to be read from the data-source /// </param> /// <param name="token"> /// The <see cref="CancellationToken"/> /// </param> /// <param name="attributes"> /// An instance of <see cref="IQueryAttributes"/> to be passed along with the request /// </param> /// <returns> /// a list of <see cref="Thing"/> that are contained by the provided <see cref="Thing"/> including the <see cref="Thing"/> itself /// </returns> public abstract Task <IEnumerable <Thing> > Read <T>(T thing, CancellationToken token, IQueryAttributes attributes = null) where T : Thing;