private static async Task ApplyV3SessionProperties( IUpstreamEdFiApiInvoker invoker, HttpRequestHeaders headers, V3SectionReference source, V2SectionReference destination, short schoolYearFromRoute) { var termDescriptorLookupKey = new TermDescriptorKey(source.SchoolId, source.SchoolYear, source.SessionName); await Task.Run(() => { var value = _termDescriptorByNaturalKey.GetOrAdd(termDescriptorLookupKey, k => GetTermDescriptorValueFromV3Session(invoker, headers, k, schoolYearFromRoute) .ConfigureAwait(false) .GetAwaiter() .GetResult()); // Is the retrieved value stale? if ((DateTime.Now - value.RetrievedDateTime).TotalSeconds > _cacheDurationSeconds.Value) { // Refresh the values TermDescriptorValue ignored; _termDescriptorByNaturalKey.TryRemove(termDescriptorLookupKey, out ignored); value = _termDescriptorByNaturalKey.GetOrAdd(termDescriptorLookupKey, k => GetTermDescriptorValueFromV3Session(invoker, headers, k, schoolYearFromRoute) .ConfigureAwait(false) .GetAwaiter() .GetResult()); } destination.TermDescriptor = value.TermDescriptor; }) .ConfigureAwait(false); }
private static async Task <SectionValues> GetV3SectionValuesAsync( IUpstreamEdFiApiInvoker invoker, HttpRequestHeaders headers, SectionLookupKey lookupKey, short schoolYearFromRoute) { // Get the referenced section by natural key var response = await invoker.Get( typeof(V3Section), headers, new[] { new KeyValuePair <string, string>("localCourseCode", lookupKey.LocalCourseCode), new KeyValuePair <string, string>("schoolId", lookupKey.SchoolId.ToString()), new KeyValuePair <string, string>("schoolYear", lookupKey.SchoolYear.ToString()), new KeyValuePair <string, string>("sectionIdentifier", lookupKey.SectionIdentifier), new KeyValuePair <string, string>("sessionName", lookupKey.SessionName), }, schoolYearFromRoute) .ConfigureAwait(false); StreamReader sr = new StreamReader(response.ResponseStream); string responseContent = await sr.ReadToEndAsync().ConfigureAwait(false); if (response.Status == HttpStatusCode.OK) { // Get the Section-derived members var v3Section = JsonConvert.DeserializeObject <V3Section[]>(responseContent, _serializerSettings).SingleOrDefault(); if (v3Section == null) { throw new Exception($"Unable to find referenced Section using the following values: {JsonConvert.SerializeObject(lookupKey, Formatting.Indented)}"); } // Invasive defensive validation against "invalid" data for V2 if (lookupKey.SchoolId != v3Section.LocationReference.SchoolId) { throw new Exception($"Unable to convert the SectionReference from host (v3.1) to client (v2.5) because the LocationReference contains a School that differs from the containing Section, which is not supported under v2.5."); } // TODO: Validate presence of V2 required values, or ensure that V3 requires them (i.e. via required collections) var sectionValues = new SectionValues( classPeriodName: v3Section.SectionClassPeriods.FirstOrDefault()?.ClassPeriodReference.ClassPeriodName ?? "Undefined", classroomIdentificationCode: v3Section.LocationReference.ClassroomIdentificationCode ?? "Undefined", sectionIdentifier: v3Section.SectionIdentifier, sequenceOfCourse: v3Section.SequenceOfCourse ?? -1, retrievedDateTime: DateTime.Now); return(sectionValues); } throw new Exception($"Error obtaining V3 Section resource during mapping of V2 SectionReference: {response.Status} - {responseContent}"); }
private static async Task ApplyPropertiesFromV3SectionAsync( IUpstreamEdFiApiInvoker invoker, HttpRequestHeaders headers, V3SectionReference source, V2SectionReference destination, short schoolYearFromRoute) { var sectionLookupKey = new SectionLookupKey(source.LocalCourseCode, source.SchoolId, source.SchoolYear, source.SectionIdentifier, source.SessionName); await Task.Run(() => { var values = _sectionValuesByNaturalKey.GetOrAdd(sectionLookupKey, k => GetV3SectionValuesAsync(invoker, headers, k, schoolYearFromRoute) .ConfigureAwait(false) .GetAwaiter() .GetResult()); // Are the retrieved values stale? if ((DateTime.Now - values.RetrievedDateTime).TotalSeconds > _cacheDurationSeconds.Value) { // Refresh the values SectionValues ignored; _sectionValuesByNaturalKey.TryRemove(sectionLookupKey, out ignored); values = _sectionValuesByNaturalKey.GetOrAdd(sectionLookupKey, k => GetV3SectionValuesAsync(invoker, headers, k, schoolYearFromRoute) .ConfigureAwait(false) .GetAwaiter() .GetResult()); } // Straight mappings from source destination.LocalCourseCode = source.LocalCourseCode; destination.SchoolId = source.SchoolId; destination.SchoolYear = source.SchoolYear; // Mappings from upstream host's Section destination.ClassPeriodName = values.ClassPeriodName; destination.ClassroomIdentificationCode = values.ClassroomIdentificationCode; destination.SequenceOfCourse = values.SequenceOfCourse; // NOTE: Assumes UniqueSectionCode is unique enough to use as the SectionIdentifier. destination.UniqueSectionCode = values.SectionIdentifier; }) .ConfigureAwait(false); }
private static async Task <TermDescriptorValue> GetTermDescriptorValueFromV3Session( IUpstreamEdFiApiInvoker invoker, HttpRequestHeaders headers, TermDescriptorKey key, short schoolYearFromRoute) { // Get the referenced section by natural key var response = await invoker.Get( typeof(V3Session), headers, new[] { new KeyValuePair <string, string>("schoolId", key.SchoolId.ToString()), new KeyValuePair <string, string>("schoolYear", key.SchoolYear.ToString()), new KeyValuePair <string, string>("sessionName", key.SessionName), }, schoolYearFromRoute) .ConfigureAwait(false); StreamReader sr = new StreamReader(response.ResponseStream); string responseContent = await sr.ReadToEndAsync().ConfigureAwait(false); if (response.Status == HttpStatusCode.OK) { // Get the Session-derived members var v3Session = JsonConvert.DeserializeObject <V3Session[]>(responseContent, _serializerSettings) .SingleOrDefault(); if (v3Session == null) { throw new Exception( $"Session with schoolId '{key.SchoolId}', schoolYear '{key.SchoolYear}' and sessionName '{key.SessionName}' was not found in host. Unable to support termDescriptor conversion for v2.5 API client."); } return(new TermDescriptorValue( VersionConverter.DescriptorV3ToV2("TermDescriptor", v3Session.TermDescriptor), DateTime.Now)); } throw new Exception( $"Error obtaining V3 Session resource during mapping of TermDescriptor: {response.Status} - {responseContent}"); }
private static async Task <string> GetSessionName( IUpstreamEdFiApiInvoker invoker, HttpRequestHeaders headers, V2SectionReference source, short schoolYear) { // Get the referenced session by example var response = await invoker.Get( typeof(V3Session), headers, new[] { new KeyValuePair <string, string>("schoolId", source.SchoolId.ToString()), new KeyValuePair <string, string>("schoolYear", source.SchoolYear.ToString()), new KeyValuePair <string, string>("termDescriptor", VersionConverter.DescriptorV2ToV3("TermDescriptor", source.TermDescriptor)) }, schoolYear) .ConfigureAwait(false); StreamReader sr = new StreamReader(response.ResponseStream); string responseContent = sr.ReadToEnd(); if (response.Status == HttpStatusCode.OK) { var v3Sessions = JsonConvert.DeserializeObject <V3Session[]>(responseContent, _serializerSettings); var distinctSessionNames = v3Sessions.Select(x => x.SessionName).Distinct().ToList(); if (distinctSessionNames.Count() > 1) { throw new Exception($"Error obtaining SessionName from remote API due to multiple values matching in the Sessions for the supplied TermDescriptor."); } return(distinctSessionNames.FirstOrDefault()); } throw new Exception( $"Error obtaining V3 Session resource during mapping of SessionName: {response.Status} - {responseContent}"); }