/// <summary>
        /// Convert the item to an auto gen item.
        /// </summary>
        /// <param name="item">The item to convert</param>
        /// <param name="currency">The currency</param>
        /// <returns></returns>
        public static AutoGen.Item CreateAutoGenItem(IShoppingCartItem item,
            string currency)
        {
            GCheckout.AutoGen.Item currentItem = new AutoGen.Item();

              currentItem.itemname = EncodeHelper.EscapeXmlChars(item.Name);
              currentItem.itemdescription =
            EncodeHelper.EscapeXmlChars(item.Description);
              currentItem.quantity = item.Quantity;

              //if there is a subscription, you may not have a unit price

              if (item.Subscription != null && item.Price > 0) {
            throw new ApplicationException(
              "The unit price must be 0 if you are using a subscription item.");
              }

              currentItem.unitprice = new AutoGen.Money();
              currentItem.unitprice.currency = currency;
              currentItem.unitprice.Value = item.Price;

              //TODO determine if we should try to catch if a UK customer tries to
              //use this value.
              if (item.Weight > 0) {
            currentItem.itemweight = new AutoGen.ItemWeight();
            currentItem.itemweight.unit = "LB"; //this is the only option.
            currentItem.itemweight.value = item.Weight;
              }

              if (item.MerchantItemID != null
            && item.MerchantItemID.Length > 0) {
            currentItem.merchantitemid = item.MerchantItemID;
              }

              if (item.MerchantPrivateItemDataNodes != null
            && item.MerchantPrivateItemDataNodes.Length > 0) {
            AutoGen.anyMultiple any = new AutoGen.anyMultiple();

            any.Any = item.MerchantPrivateItemDataNodes;
            currentItem.merchantprivateitemdata = any;
              }

              if (item.TaxTable != null &&
            item.TaxTable != AlternateTaxTable.Empty) {
            currentItem.taxtableselector = item.TaxTable.Name;
              }

              //if we have a digital item then we need to append the information
              if (item.DigitalContent != null) {
            currentItem.digitalcontent = new GCheckout.AutoGen.DigitalContent();
            //we have one of two types, email or key/url
            if (item.DigitalContent.EmailDelivery) {
              currentItem.digitalcontent.emaildelivery = true;
              currentItem.digitalcontent.emaildeliverySpecified = true;
            }
            else {
              if (item.DigitalContent.Description.Length > 0) {
            currentItem.digitalcontent.description =
              item.DigitalContent.Description;
              }
              if (item.DigitalContent.Key.Length > 0) {
            currentItem.digitalcontent.key =
              item.DigitalContent.Key;
              }
              if (item.DigitalContent.Url.Length > 0) {
            currentItem.digitalcontent.url =
              item.DigitalContent.Url;
              }
              currentItem.digitalcontent.displaydisposition
            = item.DigitalContent.GetSerializedDisposition();
            }
              }

              //see if we have subscription information
              if (item.Subscription != null) {
            if (item.Subscription.RecurrentItem == null) {
              throw new ApplicationException(
            "You must set a RecurrentItem for a subscription.");
            }
            Subscription sub = item.Subscription;
            //we have to assume the item was validated
            currentItem.subscription = new GCheckout.AutoGen.Subscription();
            GCheckout.AutoGen.Subscription autoSub = currentItem.subscription;
            if (sub.NoChargeAfter.HasValue) {
              autoSub.nochargeafter = sub.NoChargeAfter.Value;
              autoSub.nochargeafterSpecified = true;
            }
            autoSub.payments
              = new GCheckout.AutoGen.SubscriptionPayment[sub.Payments.Count];
            for (int sp = 0; sp < sub.Payments.Count; sp++) {
              SubscriptionPayment payment = sub.Payments[sp];
              autoSub.payments[sp] = new GCheckout.AutoGen.SubscriptionPayment();
              autoSub.payments[sp].maximumcharge
            = EncodeHelper.Money(currency, payment.MaximumCharge);
              if (payment.Times > 0) {
            autoSub.payments[sp].times = payment.Times;
            autoSub.payments[sp].timesSpecified = true;
              }
              autoSub.period = sub.Period;
              if (sub.RecurrentItem != null
            && sub.RecurrentItem.Subscription != null) {
            throw new ApplicationException(
              "A RecurrentItem may not contain a subscription.");
              }
              //call this method to create the recurrent item.
              autoSub.recurrentitem
            = ShoppingCartItem.CreateAutoGenItem(sub.RecurrentItem, currency);
              if (sub.StartDate.HasValue) {
            autoSub.startdate = sub.StartDate.Value;
            autoSub.startdateSpecified = true;
              }
              autoSub.type = sub.Type.ToString();
            }
              }
              return currentItem;
        }
        /// <summary>
        /// This method generates the XML for a Checkout API request. This method
        /// also calls the <b>CheckPreConditions</b> method, which verifies that
        /// if the API request indicates that the merchant will calculate tax and
        /// shipping costs, that the input data for those calculations is included
        /// in the request.
        /// </summary>
        /// <returns>This method returns the XML for a Checkout API request.
        /// </returns>
        public override byte[] GetXml()
        {
            // Verify that if the API request calls for merchant calculations, the
              // input data for those calculations is included in the request.
              //
              CheckPreConditions();

              AutoGen.CheckoutShoppingCart retVal = new AutoGen.CheckoutShoppingCart();
              retVal.shoppingcart = new AutoGen.ShoppingCart();

              // Add the Shopping cart expiration element.
              if (CartExpiration != DateTime.MinValue) {
            retVal.shoppingcart.cartexpiration = new AutoGen.CartExpiration();
            retVal.shoppingcart.cartexpiration.gooduntildate = CartExpiration;
              }

              // Add the items in the shopping cart to the API request.
              retVal.shoppingcart.items = new AutoGen.Item[_items.Count];
              for (int i = 0; i < _items.Count; i++) {

            IShoppingCartItem MyItem = _items[i] as IShoppingCartItem;
            //this can't happen at this time but if we expose a way for people to add items
            //this test needs to be peformed.
            //        if (MyItem == null) {
            //          throw new ApplicationException(
            //            "The Shopping Cart Item did not implement IShoppingCartItem." +
            //            " This is caused by someone changing the implementation of" +
            //            " GCheckout.Checkout.ShoppingCartItem.");
            //        }

            //set to a local variable of current item to lessen the change of
            //a mistake
            retVal.shoppingcart.items[i] = ShoppingCartItem.CreateAutoGenItem(MyItem, _Currency);
              }

              //because we are merging the nodes, create a new ArrayList
              ArrayList copiedMerchantPrivateData = new ArrayList();

              // Add the &lt;merchant-private-data&gt; element to the API request.
              if (MerchantPrivateData != null) {
            copiedMerchantPrivateData.Add(MakeXmlElement(MerchantPrivateData));
              }

              if (_MerchantPrivateDataNodes != null
            && _MerchantPrivateDataNodes.Count > 0) {
            for (int i = 0; i < _MerchantPrivateDataNodes.Count; i++)
              copiedMerchantPrivateData.Add(_MerchantPrivateDataNodes[i]);
              }

              if (copiedMerchantPrivateData.Count > 0) {
            AutoGen.anyMultiple any = new AutoGen.anyMultiple();

            System.Xml.XmlNode[] nodes =
              new System.Xml.XmlNode[copiedMerchantPrivateData.Count];
            copiedMerchantPrivateData.CopyTo(nodes);
            any.Any = nodes;

            retVal.shoppingcart.merchantprivatedata = any;
              }

              // Add the &lt;continue-shopping-url&gt; element to the API request.
              retVal.checkoutflowsupport =
            new AutoGen.CheckoutShoppingCartCheckoutflowsupport();

              retVal.checkoutflowsupport.Item =
            new AutoGen.MerchantCheckoutFlowSupport();

              if (ContinueShoppingUrl != null) {
            retVal.checkoutflowsupport.Item.continueshoppingurl =
              ContinueShoppingUrl;
              }
              object[] buyerMessages = BuyerMessages.ConvertMessages();
              if (buyerMessages != null && buyerMessages.Length > 0) {
            retVal.shoppingcart.buyermessages = new GCheckout.AutoGen.ShoppingCartBuyermessages();
            retVal.shoppingcart.buyermessages.Items = buyerMessages;
              }

              if (AnalyticsData != null) {
            retVal.checkoutflowsupport.Item.analyticsdata = AnalyticsData;
              }

              if (PlatformID != 0) {
            retVal.checkoutflowsupport.Item.platformid = PlatformID;
            retVal.checkoutflowsupport.Item.platformidSpecified = true;
              }

              // Add the &lt;edit-cart-url&gt; element to the API request.
              if (EditCartUrl != null) {
            retVal.checkoutflowsupport.Item.editcarturl = EditCartUrl;
              }

              // Add the &lt;request-buyer-phone-number&gt; element to the API request.
              if (RequestBuyerPhoneNumber) {
            retVal.checkoutflowsupport.Item.requestbuyerphonenumber = true;
            retVal.checkoutflowsupport.Item.requestbuyerphonenumberSpecified =
              true;
              }

              // Add the shipping methods to the API request.
              // Fix potential issue.
              if (_ShippingMethods != null && _ShippingMethods.Items != null
            && _ShippingMethods.Items.Length > 0) {
            retVal.checkoutflowsupport.Item.shippingmethods = _ShippingMethods;
              }

              //jf Tax Tables added 3/1/2007
              if (_alternateTaxTables != null) {
            _alternateTaxTables.AppendToRequest(_TaxTables);
              }

              // Add the tax tables to the API request.
              //Fix for Issue 36
              //Only if we have a tax table do we want to append it.
              if (_TaxTables != null) {
            if (
              (_TaxTables.alternatetaxtables != null
              && _TaxTables.alternatetaxtables.Length > 0)
              ||
              (_TaxTables.defaulttaxtable != null
              && _TaxTables.defaulttaxtable.taxrules != null
              && _TaxTables.defaulttaxtable.taxrules.Length > 0)
              ) {
              retVal.checkoutflowsupport.Item.taxtables = _TaxTables;
            }
              }

              // Add the merchant calculations URL to the API request.
              if (MerchantCalculationsUrl != null) {
            retVal.checkoutflowsupport.Item.merchantcalculations =
              new AutoGen.MerchantCalculations();
            retVal.checkoutflowsupport.Item.merchantcalculations.
              merchantcalculationsurl = MerchantCalculationsUrl;
              }

              // Indicate whether the merchant accepts coupons and gift certificates.
              if (AcceptMerchantCoupons) {
            retVal.checkoutflowsupport.Item.merchantcalculations.
              acceptmerchantcoupons = true;
            retVal.checkoutflowsupport.Item.merchantcalculations.
              acceptmerchantcouponsSpecified = true;
              }
              if (AcceptMerchantGiftCertificates) {
            retVal.checkoutflowsupport.Item.merchantcalculations.
              acceptgiftcertificates = true;
            retVal.checkoutflowsupport.Item.merchantcalculations.
              acceptgiftcertificatesSpecified = true;
              }

              if (_roundingRuleSet) {
            retVal.checkoutflowsupport.Item.roundingpolicy =
              new GCheckout.AutoGen.RoundingPolicy();
            retVal.checkoutflowsupport.Item.roundingpolicy.mode
              = (AutoGen.RoundingMode)Enum.Parse(typeof(AutoGen.RoundingMode),
              _roundingMode.ToString(), true);
            retVal.checkoutflowsupport.Item.roundingpolicy.rule
              = (AutoGen.RoundingRule)Enum.Parse(typeof(AutoGen.RoundingRule),
              _roundingRule.ToString(), true);
              }

              if (RequestInitialAuthDetails) {
            retVal.orderprocessingsupport = new AutoGen.OrderProcessingSupport();
            retVal.orderprocessingsupport.requestinitialauthdetailsSpecified = true;
            retVal.orderprocessingsupport.requestinitialauthdetails = true;
              }

              //See if we have any ParameterizedUrl that need to be added to the message.
              if (_ParameterizedUrls.Urls.Length > 0) {
            GCheckout.AutoGen.ParameterizedUrl[] destUrls
              = new GCheckout.AutoGen.ParameterizedUrl[_ParameterizedUrls.Urls.Length];
            for (int i = 0; i < _ParameterizedUrls.Urls.Length; i++) {
              ParameterizedUrl fromUrl = _ParameterizedUrls.Urls[i];
              GCheckout.AutoGen.ParameterizedUrl toUrl
            = new GCheckout.AutoGen.ParameterizedUrl();
              toUrl.url = fromUrl.URL;

              //ok now we have to see if params exist,
              //and if they do we need to look that array and build it out.
              if (fromUrl.Params.Length > 0) {
            GCheckout.AutoGen.UrlParameter[] destparams
              = new GCheckout.AutoGen.UrlParameter[fromUrl.Params.Length];
            for (int j = 0; j < fromUrl.Params.Length; j++) {
              UrlParamter fromParam = fromUrl.Params[j];
              GCheckout.AutoGen.UrlParameter toParam
              = new GCheckout.AutoGen.UrlParameter();
              toParam.name = fromParam.Name;
              //Use the reflection code to get the string value of the enum.
              toParam.type = fromParam.SerializedValue;
              destparams[j] = toParam;
            }
            toUrl.parameters = destparams;
              }
              destUrls[i] = toUrl; //add the url to the array.
              retVal.checkoutflowsupport.Item.parameterizedurls = destUrls;
            }
              }

              // Call the EncodeHelper.Serialize method to generate the XML for
              // the Checkout API request.
              return EncodeHelper.Serialize(retVal);
        }
        /// <summary>
        /// Convert the item to an auto gen item.
        /// </summary>
        /// <param name="item">The item to convert</param>
        /// <param name="currency">The currency</param>
        /// <returns></returns>
        public static AutoGen.Item CreateAutoGenItem(IShoppingCartItem item,
                                                     string currency)
        {
            GCheckout.AutoGen.Item currentItem = new AutoGen.Item();

            currentItem.itemname        = EncodeHelper.EscapeXmlChars(item.Name);
            currentItem.itemdescription =
                EncodeHelper.EscapeXmlChars(item.Description);
            currentItem.quantity = item.Quantity;

            //if there is a subscription, you may not have a unit price

            if (item.Subscription != null && item.Price > 0)
            {
                throw new ApplicationException(
                          "The unit price must be 0 if you are using a subscription item.");
            }

            currentItem.unitprice          = new AutoGen.Money();
            currentItem.unitprice.currency = currency;
            currentItem.unitprice.Value    = item.Price;

            //TODO determine if we should try to catch if a UK customer tries to
            //use this value.
            if (item.Weight > 0)
            {
                currentItem.itemweight       = new AutoGen.ItemWeight();
                currentItem.itemweight.unit  = "LB"; //this is the only option.
                currentItem.itemweight.value = item.Weight;
            }

            if (item.MerchantItemID != null &&
                item.MerchantItemID.Length > 0)
            {
                currentItem.merchantitemid = item.MerchantItemID;
            }

            if (item.MerchantPrivateItemDataNodes != null &&
                item.MerchantPrivateItemDataNodes.Length > 0)
            {
                AutoGen.anyMultiple any = new AutoGen.anyMultiple();

                any.Any = item.MerchantPrivateItemDataNodes;
                currentItem.merchantprivateitemdata = any;
            }

            if (item.TaxTable != null &&
                item.TaxTable != AlternateTaxTable.Empty)
            {
                currentItem.taxtableselector = item.TaxTable.Name;
            }

            //if we have a digital item then we need to append the information
            if (item.DigitalContent != null)
            {
                currentItem.digitalcontent = new GCheckout.AutoGen.DigitalContent();
                //we have one of two types, email or key/url
                if (item.DigitalContent.EmailDelivery)
                {
                    currentItem.digitalcontent.emaildelivery          = true;
                    currentItem.digitalcontent.emaildeliverySpecified = true;
                }
                else
                {
                    if (item.DigitalContent.Description.Length > 0)
                    {
                        currentItem.digitalcontent.description =
                            item.DigitalContent.Description;
                    }
                    if (item.DigitalContent.Key.Length > 0)
                    {
                        currentItem.digitalcontent.key =
                            item.DigitalContent.Key;
                    }
                    if (item.DigitalContent.Url.Length > 0)
                    {
                        currentItem.digitalcontent.url =
                            item.DigitalContent.Url;
                    }
                    currentItem.digitalcontent.displaydisposition
                        = item.DigitalContent.GetSerializedDisposition();
                }
            }

            //see if we have subscription information
            if (item.Subscription != null)
            {
                if (item.Subscription.RecurrentItem == null)
                {
                    throw new ApplicationException(
                              "You must set a RecurrentItem for a subscription.");
                }
                Subscription sub = item.Subscription;
                //we have to assume the item was validated
                currentItem.subscription = new GCheckout.AutoGen.Subscription();
                GCheckout.AutoGen.Subscription autoSub = currentItem.subscription;
                if (sub.NoChargeAfter.HasValue)
                {
                    autoSub.nochargeafter          = sub.NoChargeAfter.Value;
                    autoSub.nochargeafterSpecified = true;
                }
                autoSub.payments
                    = new GCheckout.AutoGen.SubscriptionPayment[sub.Payments.Count];
                for (int sp = 0; sp < sub.Payments.Count; sp++)
                {
                    SubscriptionPayment payment = sub.Payments[sp];
                    autoSub.payments[sp] = new GCheckout.AutoGen.SubscriptionPayment();
                    autoSub.payments[sp].maximumcharge
                        = EncodeHelper.Money(currency, payment.MaximumCharge);
                    if (payment.Times > 0)
                    {
                        autoSub.payments[sp].times          = payment.Times;
                        autoSub.payments[sp].timesSpecified = true;
                    }
                    autoSub.period = sub.Period;
                    if (sub.RecurrentItem != null &&
                        sub.RecurrentItem.Subscription != null)
                    {
                        throw new ApplicationException(
                                  "A RecurrentItem may not contain a subscription.");
                    }
                    //call this method to create the recurrent item.
                    autoSub.recurrentitem
                        = ShoppingCartItem.CreateAutoGenItem(sub.RecurrentItem, currency);
                    if (sub.StartDate.HasValue)
                    {
                        autoSub.startdate          = sub.StartDate.Value;
                        autoSub.startdateSpecified = true;
                    }
                    autoSub.type = sub.Type.ToString();
                }
            }
            return(currentItem);
        }