/// <summary> /// Flattening the Dictionary /// The input dictionary contains key value pairs in the below format /// Type 1. Key (string) , Value (string) /// Type 2. Key (string) , Value (Dictionary) /// The function will parse the dictionary values into respective class variables by directly jumping to to the switch case for Type 1 /// else it will recursively parse the inner dictionary for Type 2 /// </summary> /// <param name="dictionary"></param> private void ParseDictionaryToNewVariables(IDictionary dictionary) { foreach (string strKey in dictionary.Keys) { // Obj is the value of the dictionary key. this could either be a string or a nested inner dictionary. object obj = dictionary[strKey]; if (obj != null) { // If obj is dictionary recursively parse it if (obj is IDictionary) { parentKey = strKey; /* The below if case is when the Billing Address is present. If the key of the parent Dictionary is BillingAddress * then obj being the value of the key will contain the inner Dictionary with Billing Address Details. Send this inner Dictionary * to the BillingAddressDetails class so that it can be seperately flattened and parsed into variables. continue in this case will skip calling the * ParseDictionaryToVariables function and move to te next element in the parent Dictionary. */ if (parentKey.Equals(Operator.BillingAddress.ToString())) { billingAddress = new BillingAddressDetails((IDictionary)obj); continue; } ParseDictionaryToNewVariables((IDictionary)obj); } else { if (Enum.IsDefined(typeof(Operator), strKey)) { switch ((Operator)Enum.Parse(typeof(Operator), strKey)) { case Operator.AmazonOrderReferenceId: amazonOrderReferenceId = obj.ToString(); break; case Operator.ExpirationTimestamp: expirationTimeStamp = DateTime.Parse(obj.ToString()); break; case Operator.RequestId: requestId = obj.ToString(); break; case Operator.CreationTimestamp: creationTimestamp = DateTime.Parse(obj.ToString()); break; case Operator.LastUpdateTimestamp: lastUpdateTimestamp = DateTime.Parse(obj.ToString()); break; case Operator.ReasonCode: reasonCode = obj.ToString(); break; case Operator.ReasonDescription: reasonDescription = obj.ToString(); break; case Operator.State: /* State is the Key in XML that is same for both OrderReferenceStatus state and * PaymentAuthenticationStatus state. When flattened the XML attribute is lost but * saved in the parentKey Variable. When parentKey equals 'OrderReferenceStatus' * then parse it into orderReferenceState else into paymentAuthenticationState */ if (parentKey.Equals(Operator.OrderReferenceStatus.ToString())) { orderReferenceState = obj.ToString(); } else { paymentAuthenticationState = obj.ToString(); } break; case Operator.SellerNote: sellerNote = obj.ToString(); break; case Operator.Amount: amount = decimal.Parse(obj.ToString(), Constants.USNumberFormat); break; case Operator.CurrencyCode: currencyCode = obj.ToString(); break; case Operator.PlatformId: platformId = obj.ToString(); break; case Operator.PostalCode: postalCode = obj.ToString(); break; case Operator.Name: /* Name is the Key in XML that is same for both Buyer name and Shipping Address name * When flattened the XML attribute is lost but saved in the parentKey Variable. * when parentKey equals 'Buyer' then parse it into buyerName else into buyerShippingName */ if (parentKey.Equals(Operator.Buyer.ToString())) { buyerName = obj.ToString(); } else { buyerShippingName = obj.ToString(); } break; case Operator.Type: type = obj.ToString(); break; case Operator.Id: id = obj.ToString(); break; case Operator.Email: email = obj.ToString(); break; case Operator.Phone: phone = obj.ToString(); break; case Operator.FullDescriptor: fullDescriptor = obj.ToString(); break; case Operator.isAmazonBalanceFirst: useAmazonBalanceFirst = Boolean.Parse(obj.ToString()); break; case Operator.CountryCode: countryCode = obj.ToString(); break; case Operator.StateOrRegion: stateOrRegion = obj.ToString(); break; case Operator.AddressLine1: addressLine1 = obj.ToString(); break; case Operator.AddressLine2: addressLine2 = obj.ToString(); break; case Operator.AddressLine3: addressLine3 = obj.ToString(); break; case Operator.City: city = obj.ToString(); break; case Operator.County: county = obj.ToString(); break; case Operator.District: district = obj.ToString(); break; case Operator.DestinationType: destinationType = obj.ToString(); break; case Operator.ReleaseEnvironment: releaseEnvironment = obj.ToString(); break; case Operator.SellerOrderId: sellerOrderId = obj.ToString(); break; case Operator.CustomInformation: customInformation = obj.ToString(); break; case Operator.StoreName: storeName = obj.ToString(); break; /* The below case is when multiple constraints exist in the response. The flattening of the nested Dictionary * contains JArray of JObjects. Each Jobject contains ConstraintID and it's Description which is parsed and added to the List */ case Operator.Constraint: JArray array = JArray.Parse(obj.ToString()); hasConstraint = true; foreach (JObject item in array.Children <JObject>()) { foreach (JProperty property in item.Properties()) { string key = property.Name; string value = property.Value.ToString(); if (key.Equals(Operator.ConstraintID.ToString())) { constraintID.Add(value); } if (key.Equals(Operator.Description.ToString())) { description.Add(value); } } } break; case Operator.ConstraintID: constraintID.Add(obj.ToString()); hasConstraint = true; break; case Operator.Description: description.Add(obj.ToString()); hasConstraint = true; break; /* The below case parses two types of Authorization ID member fields. When the nested Dictionary is flattened * it contains JArray. JArray contains the member field which contains the Authorization ID. this is added to the List */ case Operator.member: if (obj.GetType() == typeof(JArray)) { JArray authIdArray = JArray.Parse(obj.ToString()); foreach (string authId in authIdArray) { authorizationId.Add(authId); } } else { authorizationId.Add(obj.ToString()); } break; case Operator.OrderLanguage: orderLanguage = obj.ToString(); break; case Operator.RequestPaymentAuthorization: requestPaymentAuthorization = Boolean.Parse(obj.ToString()); break; case Operator.PaymentServiceProviderId: paymentServiceProviderId = obj.ToString(); break; case Operator.PaymentServiceProviderOrderId: paymentServiceProviderOrderId = obj.ToString(); break; /* The below case parses the order item categories. When the nested Dictionary is flattened * it contains JArray. JArray contains the order item categories. This is added to the List */ case Operator.OrderItemCategory: if (obj.GetType() == typeof(JArray)) { JArray orderCategoryArray = JArray.Parse(obj.ToString()); foreach (string orderCategory in orderCategoryArray) { orderItemCategories.Add(orderCategory); } } else { orderItemCategories.Add(obj.ToString()); } break; case Operator.SupplementaryData: supplementaryData = obj.ToString(); break; case Operator.StaticToken: staticToken = obj.ToString(); break; } } } } } }
/// <summary> /// Flattening the Dictionary /// The input dictionary contains key value pairs in the below format /// Type 1. Key (string) , Value (string) /// Type 2. Key (string) , Value (Dictionary) /// The function will parse the dictionary values into respective class variables by directly jumping to to the switch case for Type 1 /// else it will recursively parse the inner dictionary for Type 2 /// </summary> /// <param name="dictionary"></param> private void ParseDictionaryToVariables(IDictionary dictionary) { foreach (string strKey in dictionary.Keys) { // Obj is the value of the dictionary key. this could either be a string or a nested inner dictionary. object obj = dictionary[strKey]; if (obj != null) { // If obj is dictionary recursively parse it if (obj is IDictionary) { parentKey = strKey; /* The below if case is when the Billing Address is present. If the key of the parent Dictionary is BillingAddress * then obj being the value of the key will contain the inner Dictionary with Billing Address Details. Send this inner Dictionary * to the BillingAddressDetails class so that it can be seperately flattened and parsed into variables. continue in this case will skip calling the * ParseDictionaryToVariables function and move to te next element in the parent Dictionary. */ if (parentKey.Equals(Operator.BillingAddress.ToString())) { billingAddress = new BillingAddressDetails((IDictionary)obj); continue; } ParseDictionaryToVariables((IDictionary)obj); } else { if (Enum.IsDefined(typeof(Operator), strKey)) { switch ((Operator)Enum.Parse(typeof(Operator), strKey)) { case Operator.AmazonBillingAgreementId: amazonBillingAgreementId = obj.ToString(); break; case Operator.RequestId: requestId = obj.ToString(); break; case Operator.CreationTimestamp: creationTimestamp = DateTime.Parse(obj.ToString()); break; case Operator.TimePeriodStartDate: timePeriodStartDate = DateTime.Parse(obj.ToString()); break; case Operator.TimePeriodEndDate: timePeriodEndDate = DateTime.Parse(obj.ToString()); break; case Operator.LastUpdatedTimestamp: lastUpdatedTimestamp = DateTime.Parse(obj.ToString()); break; case Operator.ReasonCode: reasonCode = obj.ToString(); break; case Operator.ReasonDescription: reasonDescription = obj.ToString(); break; case Operator.State: billingAgreementState = obj.ToString(); break; case Operator.SellerNote: sellerNote = obj.ToString(); break; case Operator.Amount: if (parentKey.Equals(Operator.AmountLimitPerTimePeriod.ToString())) { amountLimitPerTimePeriod = decimal.Parse(obj.ToString(), Constants.USNumberFormat); } else if (parentKey.Equals(Operator.CurrentRemainingBalance.ToString())) { currentRemainingBalanceAmount = decimal.Parse(obj.ToString(), Constants.USNumberFormat); } break; case Operator.CurrencyCode: if (parentKey.Equals(Operator.AmountLimitPerTimePeriod.ToString())) { amountLimitPerTimePeriodCurrencyCode = obj.ToString(); } else if (parentKey.Equals(Operator.CurrentRemainingBalance.ToString())) { currentRemainingBalanceCurrencyCode = obj.ToString(); } break; case Operator.PlatformId: platformId = obj.ToString(); break; case Operator.PostalCode: postalCode = obj.ToString(); break; case Operator.Name: /* Name is the Key in XML that is same for both Buyer name and Shipping Address name * When flattened the XML attribute is lost but saved in the parentKey Variable. * when parentKey equals 'Buyer' then parse it into buyerName else into buyerShippingName */ if (parentKey.Equals(Operator.Buyer.ToString())) { buyerName = obj.ToString(); } else { buyerShippingName = obj.ToString(); } break; case Operator.Email: email = obj.ToString(); break; case Operator.Phone: phone = obj.ToString(); break; case Operator.CountryCode: countryCode = obj.ToString(); break; case Operator.StateOrRegion: stateOrRegion = obj.ToString(); break; case Operator.AddressLine1: addressLine1 = obj.ToString(); break; case Operator.AddressLine2: addressLine2 = obj.ToString(); break; case Operator.AddressLine3: addressLine3 = obj.ToString(); break; case Operator.City: city = obj.ToString(); break; case Operator.County: county = obj.ToString(); break; case Operator.District: district = obj.ToString(); break; case Operator.DestinationType: destinationType = obj.ToString(); break; case Operator.ReleaseEnvironment: releaseEnvironment = obj.ToString(); break; case Operator.SellerOrderId: sellerOrderId = obj.ToString(); break; case Operator.SellerBillingAgreementId: sellerBillingAgreementId = obj.ToString(); break; case Operator.StoreName: storeName = obj.ToString(); break; /* The below case is when multiple constraints exist in the response. The flattening of the nested Dictionary * contains JArray of JObjects. Each Jobject contains ConstraintID and it's Description which is parsed and added to the List */ case Operator.Constraint: JArray array = JArray.Parse(obj.ToString()); hasConstraint = true; foreach (JObject item in array.Children <JObject>()) { foreach (JProperty property in item.Properties()) { string key = property.Name; string value = property.Value.ToString(); if (key.Equals(Operator.ConstraintID.ToString())) { constraintId.Add(value); } if (key.Equals(Operator.Description.ToString())) { description.Add(value); } } } break; case Operator.ConstraintID: constraintId.Add(obj.ToString()); hasConstraint = true; break; case Operator.Description: description.Add(obj.ToString()); hasConstraint = true; break; } } } } } }