private void parseOSMDocument(string osmFileLocation, ref IGPMessages message, ref List<string> nodeList, ref List<string> wayList, ref List<string> relationList, ref List<string> downloadedDocuments, string baseURL, api apiCapabilities)
        {
            try
            {
                XmlSerializer nodeSerializer = new XmlSerializer(typeof(node));
                XmlSerializer waySerializer = new XmlSerializer(typeof(way));
                XmlSerializer relationSerializer = new XmlSerializer(typeof(relation));

                string requestURL = String.Empty;

                using (System.Xml.XmlReader osmFileXmlReader = System.Xml.XmlReader.Create(osmFileLocation))
                {
                    osmFileXmlReader.MoveToContent();

                    while (osmFileXmlReader.Read())
                    {
                        if (osmFileXmlReader.IsStartElement())
                        {
                            if (osmFileXmlReader.Name == "node")
                            {
                                string currentNodeString = osmFileXmlReader.ReadOuterXml();
                                // turn the xml node representation into a node class representation
                                node currentNode = nodeSerializer.Deserialize(new System.IO.StringReader(currentNodeString)) as node;
                                if (!nodeList.Contains(currentNode.id))
                                {
                                    nodeList.Add(currentNode.id);
                                }
                            }
                            else if (osmFileXmlReader.Name == "way")
                            {
                                string currentWayString = osmFileXmlReader.ReadOuterXml();
                                // turn the xml way representation into a way class representation
                                way currentWay = waySerializer.Deserialize(new System.IO.StringReader(currentWayString)) as way;
                                if (!wayList.Contains(currentWay.id))
                                {
                                    wayList.Add(currentWay.id);
                                }

                                //if (currentWay.nd != null)
                                //{
                                //    foreach (nd wayNd in currentWay.nd)
                                //    {
                                //        if (!nodeList.Contains(wayNd.@ref))
                                //        {
                                //            string resolveMessage = string.Format(resourceManager.GetString("GPTools_OSMGPDownload_resolveid"), resourceManager.GetString("GPTools_OSM_node"), wayNd.@ref);
                                //            message.AddMessage(resolveMessage);
                                //            requestURL = baseURL + "/api/0.6/node/" + wayNd.@ref + "/full";
                                //            string nodeDownloadDocument = downloadOSMDocument(ref message, requestURL, apiCapabilities);
                                //            parseOSMDocument(nodeDownloadDocument, ref message, ref nodeList, ref wayList, ref relationList, ref downloadedDocuments, baseURL, apiCapabilities);
                                //            downloadedDocuments.Insert(1, nodeDownloadDocument);
                                //        }
                                //    }
                                //}
                            }
                            else if (osmFileXmlReader.Name == "relation")
                            {
                                string currentRelationString = osmFileXmlReader.ReadOuterXml();
                                // turn the xml way representation into a way class representation
                                relation currentRelation = relationSerializer.Deserialize(new System.IO.StringReader(currentRelationString)) as relation;
                                if (!relationList.Contains(currentRelation.id))
                                {
                                    relationList.Add(currentRelation.id);
                                }

                                foreach (object relationItem in currentRelation.Items)
                                {
                                    if (relationItem is member)
                                    {
                                        //if (((member)relationItem).type == memberType.node)
                                        //{
                                        //    string memberNodeID = ((member)relationItem).@ref;
                                        //    if (!nodeList.Contains(memberNodeID))
                                        //    {
                                        //        string resolveMessage = string.Format(resourceManager.GetString("GPTools_OSMGPDownload_resolveid"), resourceManager.GetString("GPTools_OSM_node"), memberNodeID);
                                        //        message.AddMessage(resolveMessage);
                                        //        requestURL = baseURL + "/api/0.6/node/" + memberNodeID + "/full";
                                        //        string nodeDownloadDocument = downloadOSMDocument(ref message, requestURL, apiCapabilities);
                                        //        parseOSMDocument(nodeDownloadDocument, ref message, ref nodeList, ref wayList, ref relationList, ref downloadedDocuments, baseURL, apiCapabilities);
                                        //        downloadedDocuments.Insert(1, nodeDownloadDocument);
                                        //    }
                                        //}
                                        if (((member)relationItem).type == memberType.way)
                                        {
                                            string memberWayID = ((member)relationItem).@ref;
                                            if (!wayList.Contains(memberWayID))
                                            {
                                                string resolveMessage = string.Format(resourceManager.GetString("GPTools_OSMGPDownload_resolveid"), resourceManager.GetString("GPTools_OSM_way"), memberWayID);
                                                message.AddMessage(resolveMessage);
                                                requestURL = baseURL + "/api/0.6/way/" + memberWayID + "/full";
                                                string wayDownloadDocument = downloadOSMDocument(ref message, requestURL, apiCapabilities);
                                                if (!String.IsNullOrEmpty(wayDownloadDocument))
                                                {
                                                    parseOSMDocument(wayDownloadDocument, ref message, ref nodeList, ref wayList, ref relationList, ref downloadedDocuments, baseURL, apiCapabilities);
                                                    downloadedDocuments.Insert(1, wayDownloadDocument);
                                                }
                                            }
                                        }
                                        else if (((member)relationItem).type == memberType.relation)
                                        {
                                            string memberRelationID = ((member)relationItem).@ref;
                                            if (!wayList.Contains(memberRelationID))
                                            {
                                                string resolveMessage = string.Format(resourceManager.GetString("GPTools_OSMGPDownload_resolveid"), resourceManager.GetString("GPTools_OSM_relation"), memberRelationID);
                                                message.AddMessage(resolveMessage);
                                                requestURL = baseURL + "/api/0.6/relation/" + memberRelationID + "/full";
                                                string relationDownloadDocument = downloadOSMDocument(ref message, requestURL, apiCapabilities);
                                                if (!String.IsNullOrEmpty(relationDownloadDocument))
                                                {
                                                    parseOSMDocument(relationDownloadDocument, ref message, ref nodeList, ref wayList, ref relationList, ref downloadedDocuments, baseURL, apiCapabilities);
                                                    downloadedDocuments.Insert(1, relationDownloadDocument);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    osmFileXmlReader.Close();
                }
            }
            catch (Exception ex)
            {
                message.AddError(120051, ex.Message);
            }
        }
        private string downloadOSMDocument(ref IGPMessages message, string requestURL, api apiCapabilities)
        {
            string osmDownloadDocument = String.Empty;
            HttpWebResponse httpResponse = null;

            try
            {

                // OSM does not understand URL encoded query parameters
                HttpWebRequest httpClient = HttpWebRequest.Create(requestURL) as HttpWebRequest;
                httpClient = AssignProxyandCredentials(httpClient);

                // read the timeout parameter
                int secondsToTimeout = Convert.ToInt32(apiCapabilities.timeout.seconds);
                httpClient.Timeout = secondsToTimeout * 1000;

                httpResponse = httpClient.GetResponse() as HttpWebResponse;

                osmDownloadDocument = System.IO.Path.GetTempFileName();

                using (System.IO.FileStream fileStream = new System.IO.FileStream(osmDownloadDocument, FileMode.Append, FileAccess.Write))
                {
                    using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
                    {
                        UTF8Encoding encoding = new UTF8Encoding();

                        byte[] byteBuffer = encoding.GetBytes(streamReader.ReadToEnd());
                        fileStream.Write(byteBuffer, 0, byteBuffer.Length);
                    }
                }

            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                message.AddError(120009, ex.Message);

                if (ex is WebException)
                {
                    WebException webException = ex as WebException;
                    if (webException != null)
                    {
                        if (webException.Response != null)
                        {
                            string serverErrorMessage = webException.Response.Headers["Error"];
                            if (!String.IsNullOrEmpty(serverErrorMessage))
                            {
                                message.AddError(120009, serverErrorMessage);
                            }
                        }
                    }
                }
            }
            finally
            {

                if (httpResponse != null)
                {
                    httpResponse.Close();
                }
            }
            return osmDownloadDocument;
        }
        public void UpdateMessages(ESRI.ArcGIS.esriSystem.IArray paramvalues, ESRI.ArcGIS.Geoprocessing.IGPEnvironmentManager pEnvMgr, ESRI.ArcGIS.Geodatabase.IGPMessages Messages)
        {
            IGPUtilities3 gpUtilities3 = new GPUtilitiesClass();

            // check for a valid download url
            IGPParameter downloadURLParameter = paramvalues.get_Element(in_downloadURLNumber) as IGPParameter;

            if (downloadURLParameter.HasBeenValidated == false)
            {
                IGPString downloadURLGPString = downloadURLParameter.Value as IGPString;


                if (downloadURLGPString != null)
                {
                    if (String.IsNullOrEmpty(downloadURLGPString.Value) == false)
                    {
                        try
                        {
                            Uri downloadURI = new Uri(downloadURLGPString.Value);


                            // attempt a download request from the given URL to get the server capabilities
                            m_osmAPICapabilities = CheckValidServerURL(downloadURLGPString.Value);

                            // if we can construct a valid URI  class then we are accepting the value and store it in the user settings as well
                            if (m_editorConfigurationSettings != null)
                            {
                                if (m_editorConfigurationSettings.ContainsKey("osmbaseurl"))
                                {
                                    m_editorConfigurationSettings["osmbaseurl"] = downloadURLGPString.Value;
                                }
                                else
                                {
                                    m_editorConfigurationSettings.Add("osmbaseurl", downloadURLGPString.Value);
                                }

                                OSMGPFactory.StoreOSMEditorSettings(m_editorConfigurationSettings);
                            }
                        }
                        catch (Exception ex)
                        {
                            StringBuilder errorMessage = new StringBuilder();
                            errorMessage.AppendLine(resourceManager.GetString("GPTools_OSMGPDownload_invaliddownloadurl"));
                            errorMessage.AppendLine(ex.Message);
                            Messages.ReplaceError(in_downloadURLNumber, -3, errorMessage.ToString());
                            m_osmAPICapabilities = null;
                        }
                    }
                }
            }


            if (m_osmAPICapabilities == null)
            {
                return;
            }

            // check for extent
            IGPParameter downloadExtentParameter = paramvalues.get_Element(in_downloadExtentNumber) as IGPParameter;

            if (downloadExtentParameter.HasBeenValidated == false)
            {
                IGPValue downloadExtent = gpUtilities3.UnpackGPValue(downloadExtentParameter);

                if (downloadExtent != null)
                {
                    esriGPExtentEnum gpExtent;
                    IEnvelope downloadEnvelope = gpUtilities3.GetExtent(downloadExtent, out gpExtent);

                    if (downloadEnvelope == null)
                        return;

                    if (downloadEnvelope.IsEmpty == true)
                        return;

                    ISpatialReferenceFactory spatialReferenceFactory = new SpatialReferenceEnvironmentClass() as ISpatialReferenceFactory;
                    ISpatialReference wgs84 = spatialReferenceFactory.CreateGeographicCoordinateSystem((int)esriSRGeoCSType.esriSRGeoCS_WGS1984) as ISpatialReference;

                    downloadEnvelope.Project(wgs84);

                    Marshal.ReleaseComObject(wgs84);
                    Marshal.ReleaseComObject(spatialReferenceFactory);

                    IArea downloadArea = downloadEnvelope as IArea;
                    double maximumAcceptableOSMArea = Convert.ToDouble(m_osmAPICapabilities.area.maximum, new CultureInfo("en-US"));

                    if (downloadArea.Area > maximumAcceptableOSMArea)
                    {
                        Messages.ReplaceError(in_downloadExtentNumber, -3, resourceManager.GetString("GPTools_OSMGPDownload_exceedDownloadROI"));
                    }
                }
            }

            // check for valid geodatabase path
            // if the user is pointing to a valid directory on disk, flag it as an error
            IGPParameter targetDatasetParameter = paramvalues.get_Element(out_targetDatasetNumber) as IGPParameter;
            IGPValue targetDatasetGPValue = gpUtilities3.UnpackGPValue(targetDatasetParameter);

            if (targetDatasetGPValue == null)
            {
                Messages.ReplaceError(out_targetDatasetNumber, -98, string.Format(resourceManager.GetString("GPTools_NullPointerParameterType"), targetDatasetParameter.Name));
            }


            if (targetDatasetGPValue.IsEmpty() == false)
            {
                if (System.IO.Directory.Exists(targetDatasetGPValue.GetAsText()))
                {
                    Messages.ReplaceError(out_targetDatasetNumber, -4, resourceManager.GetString("GPTools_OSMGPDownload_directory_is_not_target_dataset"));
                }
            }

            // check one of the output feature classes for version compatibility
            IGPParameter pointFeatureClassParameter = paramvalues.get_Element(out_osmPointsNumber) as IGPParameter;
            IDEFeatureClass pointDEFeatureClass = gpUtilities3.UnpackGPValue(pointFeatureClassParameter) as IDEFeatureClass;

            if (pointDEFeatureClass != null)
            {
                if (((IGPValue)pointDEFeatureClass).IsEmpty() == false)
                {
                    if (gpUtilities3.Exists((IGPValue)pointDEFeatureClass))
                    {
                        IFeatureClass ptfc = gpUtilities3.Open(gpUtilities3.UnpackGPValue(pointFeatureClassParameter)) as IFeatureClass;
                        IPropertySet osmExtensionPropertySet = ptfc.ExtensionProperties;

                        if (osmExtensionPropertySet == null)
                        {
                            Messages.ReplaceError(out_targetDatasetNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), 1, OSMClassExtensionManager.Version));
                            Messages.ReplaceError(out_osmPointsNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), 1, OSMClassExtensionManager.Version));
                            Messages.ReplaceError(out_osmLinesNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), 1, OSMClassExtensionManager.Version));
                            Messages.ReplaceError(out_osmPolygonsNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), 1, OSMClassExtensionManager.Version));
                        }
                        else
                        {
                            try
                            {
                                int extensionVersion = Convert.ToInt32(osmExtensionPropertySet.GetProperty("VERSION"));

                                object names;
                                object values;
                                osmExtensionPropertySet.GetAllProperties(out names, out values);

                                if (extensionVersion != OSMClassExtensionManager.Version)
                                {
                                    Messages.ReplaceError(out_targetDatasetNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), extensionVersion, OSMClassExtensionManager.Version));
                                    Messages.ReplaceError(out_osmPointsNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), extensionVersion, OSMClassExtensionManager.Version));
                                    Messages.ReplaceError(out_osmLinesNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), extensionVersion, OSMClassExtensionManager.Version));
                                    Messages.ReplaceError(out_osmPolygonsNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), extensionVersion, OSMClassExtensionManager.Version));
                                }
                            }
                            catch
                            {
                                Messages.ReplaceError(out_targetDatasetNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), 1, OSMClassExtensionManager.Version));
                                Messages.ReplaceError(out_osmPointsNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), 1, OSMClassExtensionManager.Version));
                                Messages.ReplaceError(out_osmLinesNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), 1, OSMClassExtensionManager.Version));
                                Messages.ReplaceError(out_osmPolygonsNumber, -5, string.Format(resourceManager.GetString("GPTools_IncompatibleExtensionVersion"), 1, OSMClassExtensionManager.Version));
                            }
                        }
                    }
                }
            }
        }