public void prepareGrid4Features(IEnumRow currentFeatures)
        {
            if (m_inspector == null)
            {
                //this is the default inspector shipped with the editor
                m_inspector = new FeatureInspector();

                SetParent(dataGridView1.Handle.ToInt32(), this.Handle.ToInt32());
            }


            DataGridView featureGridView = this.dataGridView1;

            // reset the feature grid
            featureGridView.Rows.Clear();


            if (currentFeatures == null)
            {
                return;
            }

            currentFeatures.Reset();

            IFeature currentFeature = currentFeatures.Next() as IFeature;

            Dictionary<string, ESRI.ArcGIS.OSM.OSMClassExtension.tagkey> potentialTags = new Dictionary<string, ESRI.ArcGIS.OSM.OSMClassExtension.tagkey>();


            // determine a unique collection of proposed and existing tags
            List<string> uniqueListofTags = new List<string>();
            Dictionary<string, string> commonTags = new Dictionary<string, string>();
            Geometry.esriGeometryType currentGeometryType = esriGeometryType.esriGeometryNull;
            IEnumerable<ESRI.ArcGIS.OSM.OSMClassExtension.tag> sameTags = null;

            while (currentFeature != null)
            {
                int osmTagsFieldIndex = currentFeature.Fields.FindField("osmTags");
                currentGeometryType = currentFeature.Shape.GeometryType;

                if (osmTagsFieldIndex != -1)
                {
                    ESRI.ArcGIS.OSM.OSMClassExtension.tag[] tagsOnCurrentFeature = _osmUtility.retrieveOSMTags((IRow)currentFeature, osmTagsFieldIndex, m_editor.EditWorkspace);

                    if (sameTags == null && tagsOnCurrentFeature != null)
                    {
                        sameTags = tagsOnCurrentFeature.ToArray<ESRI.ArcGIS.OSM.OSMClassExtension.tag>();
                    }
                    else if (sameTags != null && tagsOnCurrentFeature != null)
                    {
                        IEnumerable<ESRI.ArcGIS.OSM.OSMClassExtension.tag> both = tagsOnCurrentFeature.Intersect(sameTags, new ESRI.ArcGIS.OSM.OSMClassExtension.TagKeyComparer());
                        sameTags = both.ToArray<ESRI.ArcGIS.OSM.OSMClassExtension.tag>();
                    }

                    if (tagsOnCurrentFeature != null)
                    {
                        for (int index = 0; index < tagsOnCurrentFeature.Length; index++)
                        {
                            if (uniqueListofTags.Contains(tagsOnCurrentFeature[index].k) == false)
                            {
                                uniqueListofTags.Add(tagsOnCurrentFeature[index].k);
                            }

                            // check if the tag key already exists
                            if (commonTags.ContainsKey(tagsOnCurrentFeature[index].k) == true)
                            {
                                if (commonTags[tagsOnCurrentFeature[index].k] == tagsOnCurrentFeature[index].v)
                                {
                                    // the tag values still match - don't do anything
                                }
                                else
                                {
                                    // the values are different - purge the existing value
                                    commonTags[tagsOnCurrentFeature[index].k] = String.Empty;
                                }
                            }
                            else
                            {
                                // the tag doesn't exist yet in the overall collection, 
                                // add the first entry
                                commonTags.Add(tagsOnCurrentFeature[index].k, tagsOnCurrentFeature[index].v);
                            }
                        }
                    }
                }

                // determine potential tag candidates based on the osmfeature schema
                string featureString = String.Empty;

                //let's get the first domain entry and use it as the main feature theme

                for (int fieldIndex = 0; fieldIndex < currentFeature.Fields.FieldCount; fieldIndex++)
                {
                    if (String.IsNullOrEmpty(featureString))
                    {
                        if (currentFeature.Fields.get_Field(fieldIndex).Type == esriFieldType.esriFieldTypeString)
                        {
                            System.Object attributeValue = currentFeature.get_Value(fieldIndex);

                            if (attributeValue != System.DBNull.Value)
                            {
                                foreach (string lookingforDomain in m_domainDictionary.Keys)
                                {
                                    if (currentFeature.Fields.get_Field(fieldIndex).Name == lookingforDomain)
                                    {
                                        featureString = lookingforDomain + "=" + attributeValue.ToString();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }

                ESRI.ArcGIS.OSM.OSMClassExtension.osmfeature OSMInspectorFeatureType = null;

                if (m_editFeatures.Keys.Contains(featureString))
                {
                    OSMInspectorFeatureType = m_editFeatures[featureString];
                }

                if (OSMInspectorFeatureType != null)
                {
                    if (OSMInspectorFeatureType.tag != null)
                    {
                        for (int index = 0; index < OSMInspectorFeatureType.tag.Length; index++)
                        {
                            if (commonTags.ContainsKey(OSMInspectorFeatureType.tag[index].@ref) == false)
                            {
                                commonTags.Add(OSMInspectorFeatureType.tag[index].@ref, String.Empty);
                            }
                        }
                    }
                }

                currentFeature = currentFeatures.Next() as IFeature;
            }


            // get a listing of all possible tags
            Dictionary<string, ESRI.ArcGIS.OSM.OSMClassExtension.tagkey> localTags = new Dictionary<string, ESRI.ArcGIS.OSM.OSMClassExtension.tagkey>();

            foreach (ESRI.ArcGIS.OSM.OSMClassExtension.tagkey tagKeyItem in m_editTags.Values)
            {
                localTags.Add(tagKeyItem.name, tagKeyItem);
            }


            // now let's go through our unique list of proposed and existing tags
            // and fill the grid accordingly

            DataGridViewRow currentRow = null;

            foreach (KeyValuePair<string, string> osmTagValuePair in commonTags)
            {
                currentRow = new DataGridViewRow();

                // name of the tag - tag type
                DataGridViewCell currentTagCell = new DataGridViewTextBoxCell();
                currentTagCell.Value = osmTagValuePair.Key;

                // for localization include the translated language into a tooltip
                if (m_editTags.ContainsKey(osmTagValuePair.Key))
                {
                    if (!String.IsNullOrEmpty(m_editTags[osmTagValuePair.Key].displayname))
                    {
                        currentTagCell.ToolTipText = m_editTags[osmTagValuePair.Key].displayname;
                    }
                }


                currentRow.Cells.Insert(0, currentTagCell);

                // the default case is not to allow the user change the key field
                bool canEdit = false;

                if (m_editTags.ContainsKey(osmTagValuePair.Key))
                {
                    if (m_editTags[osmTagValuePair.Key].editableSpecified)
                    {
                        canEdit = m_editTags[osmTagValuePair.Key].editable;
                    }
                }

                currentRow.Cells[0].ReadOnly = !canEdit;

                // value of the tag
                // depending on the tag type we'll need to create a different cell type
                DataGridViewCell currentValueCell = null;

                if (m_editTags.ContainsKey(osmTagValuePair.Key))
                {
                    switch (m_editTags[osmTagValuePair.Key].tagtype)
                    {
                        case ESRI.ArcGIS.OSM.OSMClassExtension.tagkeyTagtype.tag_list:
                            currentValueCell = new DataGridViewComboBoxCell();
                            try
                            {
                                foreach (ESRI.ArcGIS.OSM.OSMClassExtension.tagvalue value in m_editTags[osmTagValuePair.Key].tagvalue)
                                {
                                    ((DataGridViewComboBoxCell)currentValueCell).Items.Add(value.name);
                                }
                            }
                            catch (Exception ex)
                            {
                                System.Diagnostics.Debug.WriteLine(ex.Message);
                            }
                            break;
                        case ESRI.ArcGIS.OSM.OSMClassExtension.tagkeyTagtype.tag_integer:
                            currentValueCell = new DataGridViewTextBoxCell();
                            break;
                        case ESRI.ArcGIS.OSM.OSMClassExtension.tagkeyTagtype.tag_double:
                            currentValueCell = new DataGridViewTextBoxCell();
                            break;
                        case ESRI.ArcGIS.OSM.OSMClassExtension.tagkeyTagtype.tag_string:
                            currentValueCell = new DataGridViewTextBoxCell();
                            break;
                        default:
                            currentValueCell = new DataGridViewTextBoxCell();
                            break;
                    }
                }
                else if (m_domainDictionary.ContainsKey(osmTagValuePair.Key))
                {
                    currentValueCell = new DataGridViewComboBoxCell();
                    ESRI.ArcGIS.OSM.OSMClassExtension.domain currentDomain = null;

                    switch (currentGeometryType)
                    {
                        case esriGeometryType.esriGeometryAny:
                            break;
                        case esriGeometryType.esriGeometryBag:
                            break;
                        case esriGeometryType.esriGeometryBezier3Curve:
                            break;
                        case esriGeometryType.esriGeometryCircularArc:
                            break;
                        case esriGeometryType.esriGeometryEllipticArc:
                            break;
                        case esriGeometryType.esriGeometryEnvelope:
                            break;
                        case esriGeometryType.esriGeometryLine:
                            break;
                        case esriGeometryType.esriGeometryMultiPatch:
                            break;
                        case esriGeometryType.esriGeometryMultipoint:
                            break;
                        case esriGeometryType.esriGeometryNull:
                            break;
                        case esriGeometryType.esriGeometryPath:
                            break;
                        case esriGeometryType.esriGeometryPoint:
                            currentDomain = m_domainDictionary[osmTagValuePair.Key];

                            foreach (ESRI.ArcGIS.OSM.OSMClassExtension.domainvalue item in currentDomain.domainvalue)
                            {
                                for (int geometryIndex = 0; geometryIndex < item.geometrytype.Length; geometryIndex++)
                                {
                                    if (item.geometrytype[geometryIndex] == ESRI.ArcGIS.OSM.OSMClassExtension.geometrytype.point)
                                    {
                                        try
                                        {
                                            ((DataGridViewComboBoxCell)currentValueCell).Items.Add(item.value);
                                        }
                                        catch (Exception ex)
                                        {
                                            System.Diagnostics.Debug.WriteLine(ex.Message);
                                        }
                                    }
                                }
                            }
                            break;
                        case esriGeometryType.esriGeometryPolygon:
                            currentDomain = m_domainDictionary[osmTagValuePair.Key];

                            foreach (ESRI.ArcGIS.OSM.OSMClassExtension.domainvalue item in currentDomain.domainvalue)
                            {
                                for (int geometryIndex = 0; geometryIndex < item.geometrytype.Length; geometryIndex++)
                                {
                                    if (item.geometrytype[geometryIndex] == ESRI.ArcGIS.OSM.OSMClassExtension.geometrytype.polygon)
                                    {
                                        try
                                        {
                                            ((DataGridViewComboBoxCell)currentValueCell).Items.Add(item.value);
                                        }
                                        catch (Exception ex)
                                        {
                                            System.Diagnostics.Debug.WriteLine(ex.Message);
                                        }
                                    }
                                }
                            }
                            break;
                        case esriGeometryType.esriGeometryPolyline:
                            currentDomain = m_domainDictionary[osmTagValuePair.Key];

                            foreach (ESRI.ArcGIS.OSM.OSMClassExtension.domainvalue item in currentDomain.domainvalue)
                            {
                                for (int geometryIndex = 0; geometryIndex < item.geometrytype.Length; geometryIndex++)
                                {
                                    if (item.geometrytype[geometryIndex] == ESRI.ArcGIS.OSM.OSMClassExtension.geometrytype.line)
                                    {
                                        try
                                        {
                                            ((DataGridViewComboBoxCell)currentValueCell).Items.Add(item.value);
                                        }
                                        catch (Exception ex)
                                        {
                                            System.Diagnostics.Debug.WriteLine(ex.Message);
                                        }
                                    }
                                }
                            }
                            break;
                        case esriGeometryType.esriGeometryRay:
                            break;
                        case esriGeometryType.esriGeometryRing:
                            break;
                        case esriGeometryType.esriGeometrySphere:
                            break;
                        case esriGeometryType.esriGeometryTriangleFan:
                            break;
                        case esriGeometryType.esriGeometryTriangleStrip:
                            break;
                        case esriGeometryType.esriGeometryTriangles:
                            break;
                        default:
                            break;
                    }
                }
                else
                { // unkown keys are treated as strings
                    currentValueCell = new DataGridViewTextBoxCell();
                }

                // add the value only we have a value and if the tag is common among all features
                if (String.IsNullOrEmpty(osmTagValuePair.Value) == false)
                {
                    ESRI.ArcGIS.OSM.OSMClassExtension.tag compareTag = new ESRI.ArcGIS.OSM.OSMClassExtension.tag();
                    compareTag.k = osmTagValuePair.Key;

                    if (sameTags.Contains(compareTag, new ESRI.ArcGIS.OSM.OSMClassExtension.TagKeyComparer()))
                    {
                        currentValueCell.Value = osmTagValuePair.Value;
                    }
                }

                // for localization include the translated language into a tooltip
                if (m_editTags.ContainsKey((string)currentTagCell.Value))
                {
                    if (!String.IsNullOrEmpty((string)currentValueCell.Value))
                    {
                        ESRI.ArcGIS.OSM.OSMClassExtension.tagvalue[] possibleValues = m_editTags[(string)currentTagCell.Value].tagvalue;

                        if (possibleValues != null)
                        {
                            for (int valueIndex = 0; valueIndex < possibleValues.Length; valueIndex++)
                            {
                                if (currentValueCell.Value.Equals(possibleValues[valueIndex].name) == true)
                                {
                                    if (!String.IsNullOrEmpty(possibleValues[valueIndex].displayname))
                                    {
                                        currentValueCell.ToolTipText = possibleValues[valueIndex].displayname;
                                    }
                                }
                            }
                        }
                    }
                }

                currentRow.Cells.Insert(1, currentValueCell);

                // the assumption here is that values are usually open to user edits
                canEdit = true;
                currentRow.Cells[1].ReadOnly = !canEdit;

                DataGridViewLinkCell currentInfoCell = new DataGridViewLinkCell();
                currentInfoCell.LinkBehavior = LinkBehavior.SystemDefault;

                if (m_editTags.ContainsKey(osmTagValuePair.Key))
                {
                    if (String.IsNullOrEmpty(m_editTags[osmTagValuePair.Key].infoURL))
                    {
                        currentInfoCell.Value = new Uri(m_baseInfoURI + HttpUtility.UrlEncode("Key:" + osmTagValuePair.Key));
                    }
                    else
                    {
                        currentInfoCell.Value = new Uri(m_editTags[osmTagValuePair.Key].infoURL);
                    }
                    currentRow.Cells.Insert(2, currentInfoCell);
                }
                else
                {
                    currentInfoCell.Value = new Uri(m_baseInfoURI + HttpUtility.UrlEncode("Key:" + osmTagValuePair.Key));
                }

                featureGridView.Rows.Add(currentRow);

                if (localTags.ContainsKey(osmTagValuePair.Key))
                {
                    localTags.Remove(osmTagValuePair.Key);
                }
            }

            // add the list in the first column of the last row
            DataGridViewRow lastRow = new DataGridViewRow();
            DataGridViewComboBoxCell currentKeyCell = new DataGridViewComboBoxCell();
            try
            {
                // show a sorted list of tags to the user
                IEnumerable<string> sortedKeys = localTags.Keys.OrderBy(myKey => myKey);

                foreach (string currentKey in sortedKeys)
                {
                    currentKeyCell.Items.Add(currentKey);
                }
            }
            catch { }

            lastRow.Cells.Insert(0, currentKeyCell);

            featureGridView.Rows.Add(lastRow);

        }
        public void Execute(ESRI.ArcGIS.esriSystem.IArray paramvalues, ESRI.ArcGIS.esriSystem.ITrackCancel TrackCancel, ESRI.ArcGIS.Geoprocessing.IGPEnvironmentManager envMgr, ESRI.ArcGIS.Geodatabase.IGPMessages message)
        {
            _message = message;

            // classes to carry out the basic client/server communication
            HttpWebResponse httpResponse = null;
            string changeSetID = "-1";
            IGPString baseURLGPString = new GPStringClass();
            ICursor searchCursor = null;

            IGPUtilities3 gpUtilities3 = new GPUtilitiesClass();

            if (TrackCancel == null)
            {
                TrackCancel = new CancelTrackerClass();
            }

            IGPParameter userNameParameter = paramvalues.get_Element(in_userNameNumber) as IGPParameter;
            IGPString userNameGPValue = gpUtilities3.UnpackGPValue(userNameParameter) as IGPString;

            IHttpBasicGPValue userCredentialGPValue = new HttpBasicGPValue();

            if (userNameGPValue != null)
            {
                userCredentialGPValue.UserName = userNameGPValue.Value;
            }
            else
            {
                return;
            }

            IGPParameter passwordParameter = paramvalues.get_Element(in_passwordNumber) as IGPParameter;
            IGPStringHidden passwordGPValue = gpUtilities3.UnpackGPValue(passwordParameter) as IGPStringHidden;

            if (passwordGPValue != null)
            {
                userCredentialGPValue.PassWord = passwordGPValue.Value;
            }
            else
            {
                return;
            }

            ITable revisionTable = null;
            int secondsToTimeout = 10;

            try
            {
                UpdateMessages(paramvalues, envMgr, message);

                if ((message.MaxSeverity == esriGPMessageSeverity.esriGPMessageSeverityAbort) ||
                    (message.MaxSeverity == esriGPMessageSeverity.esriGPMessageSeverityError))
                {
                    message.AddMessages(message);
                    return;
                }

                IGPParameter baseURLParameter = paramvalues.get_Element(in_uploadURLNumber) as IGPParameter;
                baseURLGPString = gpUtilities3.UnpackGPValue(baseURLParameter) as IGPString;

                IGPParameter commentParameter = paramvalues.get_Element(in_uploadCommentNumber) as IGPParameter;
                IGPString uploadCommentGPString = gpUtilities3.UnpackGPValue(commentParameter) as IGPString;

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

                System.Xml.Serialization.XmlSerializer serializer = null;
                serializer = new XmlSerializer(typeof(osm));

                osm createChangeSetOSM = new osm();
                string user_displayname = "";
                int userID = -1;

                // set the "default" value of the OSM server
                int maxElementsinChangeSet = 50000;

                HttpWebRequest httpClient = HttpWebRequest.Create(baseURLGPString.Value + "/api/capabilities") as HttpWebRequest;
                httpClient = OSMGPDownload.AssignProxyandCredentials(httpClient);
                SetBasicAuthHeader(httpClient, userCredentialGPValue.EncodedUserNamePassWord);
                httpClient.Timeout = secondsToTimeout * 1000;

                createChangeSetOSM.generator = m_Generator;
                createChangeSetOSM.version = "0.6";

                changeset createChangeSet = new changeset();
                createChangeSet.id = "0";
                createChangeSet.open = changesetOpen.@false;

                List<tag> changeSetTags = new List<tag>();

                tag createdByTag = new tag();
                createdByTag.k = "created_by";
                createdByTag.v = "ArcGIS Editor for OpenStreetMap";
                changeSetTags.Add(createdByTag);

                tag commentTag = new tag();
                commentTag.k = "comment";
                commentTag.v = uploadCommentGPString.Value;
                changeSetTags.Add(commentTag);

                createChangeSet.tag = changeSetTags.ToArray();
                createChangeSetOSM.Items = new object[] { createChangeSet };

                api apiCapabilities = null;

                // retrieve some server settings

                try
                {
                    httpResponse = httpClient.GetResponse() as HttpWebResponse;

                    osm osmCapabilities = null;

                    Stream stream = httpResponse.GetResponseStream();

                    XmlTextReader xmlReader = new XmlTextReader(stream);
                    osmCapabilities = serializer.Deserialize(xmlReader) as osm;
                    xmlReader.Close();

                    apiCapabilities = osmCapabilities.Items[0] as api;
                    httpResponse.Close();
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                    message.AddWarning(ex.Message);
                }

                if (apiCapabilities != null)
                {
                    // read the timeout parameter
                    secondsToTimeout = Convert.ToInt32(apiCapabilities.timeout.seconds);
                    httpClient.Timeout = secondsToTimeout * 1000;

                    // update the setting of allowed features per changeset from the actual capabilities response
                    maxElementsinChangeSet = Convert.ToInt32(apiCapabilities.changesets.maximum_elements);
                }

                // retrieve some information about the user
                try
                {
                    httpClient = null;
                    httpClient = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/user/details") as HttpWebRequest;
                    httpClient = OSMGPDownload.AssignProxyandCredentials(httpClient);
                    SetBasicAuthHeader(httpClient, userCredentialGPValue.EncodedUserNamePassWord);

                    httpResponse = httpClient.GetResponse() as HttpWebResponse;

                    osm osmCapabilities = null;

                    Stream stream = httpResponse.GetResponseStream();

                    XmlTextReader xmlReader = new XmlTextReader(stream);
                    osmCapabilities = serializer.Deserialize(xmlReader) as osm;
                    xmlReader.Close();
                    user userInformation = osmCapabilities.Items[0] as user;

                    if (userInformation != null)
                    {
                        user_displayname = userInformation.display_name;
                        userID = Convert.ToInt32(userInformation.id);
                    }
                }

                catch (ArgumentOutOfRangeException ex)
                {
                    message.AddError(120044, ex.Message);
                    return;
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                    message.AddWarning(ex.Message);
                }

                IGPParameter revisionTableParameter = paramvalues.get_Element(in_changesTablesNumber) as IGPParameter;
                int featureUpdateCounter = 0;

                IQueryFilter revisionTableQueryFilter = null;

                try
                {
                    gpUtilities3.DecodeTableView(gpUtilities3.UnpackGPValue(revisionTableParameter), out revisionTable, out revisionTableQueryFilter);
                }
                catch
                {
                    message.AddError(120045,resourceManager.GetString("GPTools_OSMGPUpload_missingRevisionTable"));
                    return;
                }

                int revChangeSetIDFieldIndex = revisionTable.Fields.FindField("osmchangeset");
                int revActionFieldIndex = revisionTable.Fields.FindField("osmaction");
                int revElementTypeFieldIndex = revisionTable.Fields.FindField("osmelementtype");
                int revVersionFieldIndex = revisionTable.Fields.FindField("osmversion");
                int revFCNameFieldIndex = revisionTable.Fields.FindField("sourcefcname");
                int revOldIDFieldIndex = revisionTable.Fields.FindField("osmoldid");
                int revNewIDFieldIndex = revisionTable.Fields.FindField("osmnewid");
                int revStatusFieldIndex = revisionTable.Fields.FindField("osmstatus");
                int revStatusCodeFieldIndex = revisionTable.Fields.FindField("osmstatuscode");
                int revErrorMessageFieldIndex = revisionTable.Fields.FindField("osmerrormessage");
                int revLongitudeFieldIndex = revisionTable.Fields.FindField("osmlon");
                int revLatitudeFieldIndex = revisionTable.Fields.FindField("osmlat");

                // let's find all the rows that have a different status than OK - meaning success
                IQueryFilter queryFilter = new QueryFilterClass();

                searchCursor = revisionTable.Search(queryFilter, false);
                IRow searchRowToUpdate = null;

                // lookup table to adjust all osm ID references if there are know entities
                Dictionary<long, long> nodeosmIDLookup = new Dictionary<long, long>();
                Dictionary<long, long> wayosmIDLookup = new Dictionary<long, long>();
                Dictionary<long, long> relationosmIDLookup = new Dictionary<long, long>();

                // let's pre-populate the lookup IDs with already know entities
                // it is necessary if the revision table is used more than once and in different sessions
                queryFilter.WhereClause = "NOT " + revisionTable.SqlIdentifier("osmnewid") + " IS NULL";

                using (ComReleaser comReleaser = new ComReleaser())
                {
                    ICursor searchIDCursor = revisionTable.Search(queryFilter, false);
                    comReleaser.ManageLifetime(searchIDCursor);

                    IRow searchRow = searchIDCursor.NextRow();
                    comReleaser.ManageLifetime(searchRow);

                    while (searchRow != null)
                    {
                        if (revOldIDFieldIndex > -1 && revNewIDFieldIndex > -1)
                        {
                            string elementType = Convert.ToString(searchRow.get_Value(revElementTypeFieldIndex));

                            switch (elementType)
                            {
                                case "node":
                                    if (nodeosmIDLookup.ContainsKey(Convert.ToInt64(searchRow.get_Value(revOldIDFieldIndex))) == false)
                                    {
                                        nodeosmIDLookup.Add(Convert.ToInt64(searchRow.get_Value(revOldIDFieldIndex)), Convert.ToInt64(searchRow.get_Value(revNewIDFieldIndex)));
                                    }
                                    break;
                                case "way":
                                    if (wayosmIDLookup.ContainsKey(Convert.ToInt64(searchRow.get_Value(revOldIDFieldIndex))) == false)
                                    {
                                        wayosmIDLookup.Add(Convert.ToInt64(searchRow.get_Value(revOldIDFieldIndex)), Convert.ToInt64(searchRow.get_Value(revNewIDFieldIndex)));
                                    }
                                    break;
                                case "relation":
                                    if (relationosmIDLookup.ContainsKey(Convert.ToInt64(searchRow.get_Value(revOldIDFieldIndex))) == false)
                                    {
                                        relationosmIDLookup.Add(Convert.ToInt64(searchRow.get_Value(revOldIDFieldIndex)), Convert.ToInt64(searchRow.get_Value(revNewIDFieldIndex)));
                                    }
                                    break;
                                default:
                                    break;
                            }
                        }
                        searchRow = searchIDCursor.NextRow();
                    }
                }

                IFeatureClass pointFeatureClass = null;
                int pointOSMIDFieldIndex = -1;
                IFeatureClass lineFeatureClass = null;
                IFeatureClass polygonFeatureClass = null;
                ITable relationTable = null;

                int osmDelimiterPosition = ((IDataset)revisionTable).Name.IndexOf("_osm_");
                string osmBaseName = ((IDataset)revisionTable).Name.Substring(0, osmDelimiterPosition);

                IFeatureWorkspace osmFeatureWorkspace = ((IDataset)revisionTable).Workspace as IFeatureWorkspace;

                if (osmFeatureWorkspace != null)
                {
                    pointFeatureClass = osmFeatureWorkspace.OpenFeatureClass(osmBaseName + "_osm_pt");
                    pointOSMIDFieldIndex = pointFeatureClass.FindField("OSMID");
                    lineFeatureClass = osmFeatureWorkspace.OpenFeatureClass(osmBaseName + "_osm_ln");
                    polygonFeatureClass = osmFeatureWorkspace.OpenFeatureClass(osmBaseName + "_osm_ply");
                    relationTable = osmFeatureWorkspace.OpenTable(osmBaseName + "_osm_relation");
                }

                // determine version of extension
                int internalExtensionVersion = pointFeatureClass.OSMExtensionVersion();

                string sData = OsmRest.SerializeUtils.CreateXmlSerializable(createChangeSetOSM, serializer, Encoding.ASCII, "text/xml");
                HttpWebRequest httpClient2 = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/changeset/create") as HttpWebRequest;
                httpClient2.Method = "PUT";
                httpClient2 = OSMGPDownload.AssignProxyandCredentials(httpClient2);
                SetBasicAuthHeader(httpClient2, userCredentialGPValue.EncodedUserNamePassWord);
                httpClient2.Timeout = secondsToTimeout * 1000;

                try
                {
                    Stream requestStream = httpClient2.GetRequestStream();
                    StreamWriter mywriter = new StreamWriter(requestStream);

                    mywriter.Write(sData);
                    mywriter.Close();

                    WebResponse clientResponse = httpClient2.GetResponse();
                    Stream readStream = clientResponse.GetResponseStream();
                    StreamReader streamReader = new StreamReader(readStream);
                    changeSetID = streamReader.ReadToEnd();
                    streamReader.Close();

                    message.AddMessage(String.Format(resourceManager.GetString("GPTools_OSMGPUpload_openChangeSet"), changeSetID));

                }
                catch (Exception ex)
                {
                    if (httpResponse != null)
                    {
                        if (httpResponse.StatusCode != System.Net.HttpStatusCode.OK)
                        {
                            foreach (var errorItem in httpResponse.Headers.GetValues("Error"))
                            {
                                message.AddError(120009, errorItem);
                            }

                            message.AddError(120009, httpResponse.StatusCode.ToString());
                            message.AddError(120009, ex.Message);
                        }
                    }
                    else
                    {
                        message.AddError(120047, ex.Message);
                    }

                    return;
                }

                IGPParameter uploadFormatParameter = paramvalues.get_Element(in_uploadFormatNumber) as IGPParameter;
                IGPBoolean useOSMChangeFormatGPValue = gpUtilities3.UnpackGPValue(uploadFormatParameter) as IGPBoolean;

                // Al Hack
                if (useOSMChangeFormatGPValue == null)
                {
                    useOSMChangeFormatGPValue = new GPBoolean();
                    useOSMChangeFormatGPValue.Value = false;
                }

                SQLFormatter sqlFormatter = new SQLFormatter(revisionTable);

                if (useOSMChangeFormatGPValue.Value == true)
                {
                    #region osmchange upload format

                    osmChange osmChangeDocument = new osmChange();
                    osmChangeDocument.generator = m_Generator;
                    osmChangeDocument.version = "0.6";

                    // xml elements to describe the changeset
                    create uploadCreates = null;
                    modify uploadModify = null;
                    delete uploadDelete = null;

                    // helper classes to keep track of elements entered into a changeset
                    List<object> listOfCreates = null;
                    List<object> listOfModifies = null;
                    List<object> listOfDeletes = null;

                    List<object> changeSetItems = new List<object>();

                    #region upload create actions
                    // loop through creates
                    queryFilter.WhereClause = "(" + sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                        + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                        + sqlFormatter.SqlIdentifier("osmaction") + " = 'create'";

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        searchCursor = revisionTable.Search(queryFilter, false);
                        comReleaser.ManageLifetime(searchCursor);

                        searchRowToUpdate = searchCursor.NextRow();
                        comReleaser.ManageLifetime(searchRowToUpdate);

                        // if we have at least one entry with a create action, then add the 'create' element to the changeset representation
                        if (searchRowToUpdate != null)
                        {
                            uploadCreates = new create();
                            listOfCreates = new List<object>();
                        }

                        while (searchRowToUpdate != null)
                        {
                            try
                            {
                                if (TrackCancel.Continue() == false)
                                {
                                    closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                    return;
                                }

                                string action = String.Empty;
                                if (revActionFieldIndex != -1)
                                {
                                    action = searchRowToUpdate.get_Value(revActionFieldIndex) as string;
                                }
                                string elementType = String.Empty;
                                if (revElementTypeFieldIndex != -1)
                                {
                                    elementType = searchRowToUpdate.get_Value(revElementTypeFieldIndex) as string;
                                }

                                string sourceFCName = String.Empty;
                                if (revFCNameFieldIndex != -1)
                                {
                                    sourceFCName = searchRowToUpdate.get_Value(revFCNameFieldIndex) as string;
                                }

                                long osmOldID = -1;
                                if (revOldIDFieldIndex != -1)
                                {
                                    osmOldID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                }

                                // if the overall number of uploaded elements is too big for a single changeset we do need to split it up
                                // into multiple sets
                                if (featureUpdateCounter > 0 & (featureUpdateCounter % maxElementsinChangeSet) == 0)
                                {
                                    // add any outstanding creations to the changeset items
                                    if (listOfCreates != null && uploadCreates != null)
                                    {
                                        uploadCreates.Items = listOfCreates.ToArray();
                                        // in case there are any creates let's add them to the changeset document
                                        changeSetItems.Add(uploadCreates);
                                    }

                                    // add all the changeset items to the changeset document
                                    osmChangeDocument.Items = changeSetItems.ToArray();

                                    // submit changeset
                                    try
                                    {
                                        httpClient = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/changeset/" + changeSetID + "/upload") as HttpWebRequest;
                                        httpClient = OSMGPDownload.AssignProxyandCredentials(httpClient);
                                        httpClient.Method = "POST";
                                        SetBasicAuthHeader(httpClient, userCredentialGPValue.EncodedUserNamePassWord);
                                        httpClient.Timeout = secondsToTimeout * 1000;

                                        string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(osmChangeDocument, null, Encoding.UTF8, "text/xml");

                                        message.AddMessage(String.Format(resourceManager.GetString("GPTools_OSMGPUpload_featureSubmit"), featureUpdateCounter));

                                        OsmRest.HttpUtils.Post(httpClient, sContent);

                                        httpResponse = httpClient.GetResponse() as HttpWebResponse;
                                        diffResult diffResultResonse = OsmRest.HttpUtils.GetResponse(httpResponse);

                                        // parse changes locally and update local data sources
                                        if (diffResultResonse != null)
                                        {
                                            ParseResultDiff(diffResultResonse, revisionTable, pointFeatureClass, lineFeatureClass, polygonFeatureClass, relationTable, user_displayname, userID, changeSetID, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                        }

                                    }
                                    catch (Exception ex)
                                    {
                                        closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                        message.AddError(120009, ex.Message);

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

                                        if (httpResponse != null)
                                        {
                                            httpResponse.Close();
                                        }
                                        return;
                                    }
                                    finally
                                    {
                                        // reset the list and containers of modifications for the next batch
                                        listOfCreates.Clear();
                                        changeSetItems.Clear();

                                        if (httpResponse != null)
                                        {
                                            httpResponse.Close();
                                        }
                                    }

                                    if (TrackCancel.Continue() == false)
                                    {
                                        closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                        return;
                                    }

                                    CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                                }

                                switch (elementType)
                                {
                                    case "node":
                                        node createNode = CreateNodeRepresentation(pointFeatureClass, action, osmOldID, changeSetID, 1, null, internalExtensionVersion);
                                        listOfCreates.Add(createNode);
                                        break;
                                    case "way":
                                        way createWay = null;
                                        if (sourceFCName.Contains("_osm_ln"))
                                        {
                                            createWay = CreateWayRepresentation(lineFeatureClass, action, osmOldID, changeSetID, 1, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                        }
                                        else if (sourceFCName.Contains("_osm_ply"))
                                        {
                                            createWay = CreateWayRepresentation(polygonFeatureClass, action, osmOldID, changeSetID, 1, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                        }
                                        listOfCreates.Add(createWay);
                                        break;
                                    case "relation":
                                        relation createRelation = null;
                                        if (sourceFCName.Contains("_osm_ln"))
                                        {
                                            createRelation = CreateRelationRepresentation((ITable)lineFeatureClass, action, osmOldID, changeSetID, 1, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                        }
                                        else if (sourceFCName.Contains("_osm_ply"))
                                        {
                                            createRelation = CreateRelationRepresentation((ITable)polygonFeatureClass, action, osmOldID, changeSetID, 1, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                        }
                                        else if (sourceFCName.Contains("_osm_relation"))
                                        {
                                            createRelation = CreateRelationRepresentation(relationTable, action, osmOldID, changeSetID, 1, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                        }
                                        listOfCreates.Add(createRelation);
                                        break;
                                    default:
                                        break;
                                }
                                // increment the counter keeping track of the submitted changes
                                featureUpdateCounter = featureUpdateCounter + 1;
                            }
                            catch
                            {
                            }
                            searchRowToUpdate = searchCursor.NextRow();
                        }

                        if (listOfCreates != null && uploadCreates != null)
                        {
                            // sort the list of created elements in the order of nodes, ways, relations
                            listOfCreates.Sort(new OSMElementComparer());

                            uploadCreates.Items = listOfCreates.ToArray();
                            // in case there are any creates let's add them to the changeset document
                            changeSetItems.Add(uploadCreates);
                        }
                    }
                    #endregion

                    #region upload modify actions
                    // loop through modifies
                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        queryFilter.WhereClause = "(" +
                            sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                            + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                            + sqlFormatter.SqlIdentifier("osmaction") + " = 'modify'";

                        searchCursor = revisionTable.Search(queryFilter, false);
                        comReleaser.ManageLifetime(searchCursor);

                        searchRowToUpdate = searchCursor.NextRow();

                        if (searchRowToUpdate != null)
                        {
                            uploadModify = new modify();
                            listOfModifies = new List<object>();
                        }

                        while (searchRowToUpdate != null)
                        {
                            if (TrackCancel.Continue() == false)
                            {
                                closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                return;
                            }

                            try
                            {
                                string action = String.Empty;
                                if (revActionFieldIndex != -1)
                                {
                                    action = searchRowToUpdate.get_Value(revActionFieldIndex) as string;
                                }

                                string elementType = String.Empty;
                                if (revElementTypeFieldIndex != -1)
                                {
                                    elementType = searchRowToUpdate.get_Value(revElementTypeFieldIndex) as string;
                                }

                                string sourceFCName = String.Empty;
                                if (revFCNameFieldIndex != -1)
                                {
                                    sourceFCName = searchRowToUpdate.get_Value(revFCNameFieldIndex) as string;
                                }

                                long osmOldID = -1;
                                if (revOldIDFieldIndex != -1)
                                {
                                    osmOldID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                }

                                // if the overall number of uploaded elements is too big for a single changeset we do need to split it up
                                long modifyID = -1;
                                if (revNewIDFieldIndex != -1)
                                {
                                    object osmIDValue = searchRowToUpdate.get_Value(revNewIDFieldIndex);

                                    if (osmIDValue == DBNull.Value)
                                    {
                                        osmIDValue = osmOldID;
                                    }

                                    try
                                    {
                                        modifyID = Convert.ToInt64(osmIDValue);
                                    }
                                    catch { }

                                    // modifies should only happen to osm IDs > 0
                                    // if that condition is not met let's skip this feature as something is not right
                                    if (modifyID < 0)
                                    {
                                        searchRowToUpdate = searchCursor.NextRow();
                                        continue;
                                    }
                                }

                                int osmVersion = -1;
                                if (revVersionFieldIndex != -1)
                                {
                                    osmVersion = Convert.ToInt32(searchRowToUpdate.get_Value(revVersionFieldIndex));
                                }

                                // into multiple sets
                                if ((featureUpdateCounter % maxElementsinChangeSet) == 0)
                                {
                                    // add any outstanding modifications to the changeset items
                                    if (listOfModifies != null && uploadModify != null)
                                    {
                                        uploadModify.Items = listOfModifies.ToArray();
                                        // in case there are any creates let's add them to the changeset document
                                        changeSetItems.Add(uploadModify);
                                    }

                                    // add all the changeset items to the changeset document
                                    osmChangeDocument.Items = changeSetItems.ToArray();

                                    // submit changeset
                                    try
                                    {
                                        httpClient = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/changeset/" + changeSetID + "/upload") as HttpWebRequest;
                                        httpClient = OSMGPDownload.AssignProxyandCredentials(httpClient);
                                        httpClient.Method = "POST";
                                        SetBasicAuthHeader(httpClient, userCredentialGPValue.EncodedUserNamePassWord);
                                        httpClient.Timeout = secondsToTimeout * 1000;

                                        string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(osmChangeDocument, null, Encoding.UTF8, "text/xml");
                                        OsmRest.HttpUtils.Post(httpClient, sContent);

                                        httpResponse = httpClient.GetResponse() as HttpWebResponse;
                                        diffResult diffResultResonse = OsmRest.HttpUtils.GetResponse(httpResponse);

                                        // parse changes locally and update local data sources
                                        if (diffResultResonse != null)
                                        {
                                            ParseResultDiff(diffResultResonse, revisionTable, pointFeatureClass, lineFeatureClass, polygonFeatureClass, relationTable, user_displayname, userID, changeSetID, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                        }

                                    }
                                    catch (Exception ex)
                                    {
                                        closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                        message.AddError(120009, ex.Message);

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

                                            if (httpResponse != null)
                                            {
                                                httpResponse.Close();
                                            }
                                        }
                                        return;
                                    }
                                    finally
                                    {
                                        // reset the list and containers of modifications for the next batch
                                        listOfModifies.Clear();
                                        changeSetItems.Clear();

                                        if (httpResponse != null)
                                        {
                                            httpResponse.Close();
                                        }
                                    }

                                    if (TrackCancel.Continue() == false)
                                    {
                                        closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                        return;
                                    }

                                    CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                                }

                                switch (elementType)
                                {
                                    case "node":
                                        node updateNode = CreateNodeRepresentation(pointFeatureClass, action, modifyID, changeSetID, osmVersion, null, internalExtensionVersion);
                                        listOfModifies.Add(updateNode);
                                        break;
                                    case "way":
                                        way updateWay = null;
                                        if (sourceFCName.Contains("_osm_ln"))
                                        {
                                            updateWay = CreateWayRepresentation(lineFeatureClass, action, modifyID, changeSetID, osmVersion, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                        }
                                        else if (sourceFCName.Contains("_osm_ply"))
                                        {
                                            updateWay = CreateWayRepresentation(polygonFeatureClass, action, modifyID, changeSetID, osmVersion, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                        }
                                        listOfModifies.Add(updateWay);
                                        break;
                                    case "relation":
                                        relation updateRelation = null;
                                        if (sourceFCName.Contains("_osm_ln"))
                                        {
                                            updateRelation = CreateRelationRepresentation((ITable)lineFeatureClass, action, modifyID, changeSetID, osmVersion, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                        }
                                        else if (sourceFCName.Contains("_osm_ply"))
                                        {
                                            updateRelation = CreateRelationRepresentation((ITable)polygonFeatureClass, action, modifyID, changeSetID, osmVersion, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                        }
                                        else if (sourceFCName.Contains("_osm_relation"))
                                        {
                                            updateRelation = CreateRelationRepresentation(relationTable, action, modifyID, changeSetID, osmVersion, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                        }
                                        listOfModifies.Add(updateRelation);
                                        break;
                                    default:
                                        break;
                                }

                                // track the update/sync requests against the server
                                featureUpdateCounter = featureUpdateCounter + 1;
                            }
                            catch
                            {
                            }

                            searchRowToUpdate = searchCursor.NextRow();
                        }

                        if (listOfModifies != null && uploadModify != null)
                        {
                            uploadModify.Items = listOfModifies.ToArray();
                            // in case there are any creates let's add them to the changeset document
                            changeSetItems.Add(uploadModify);
                        }

                    }
                    #endregion

                    #region upload delete actions
                    // loop through deletes in "reverse" - relation, then way, then node
                    string[] elementTypes = new string[] { "relation", "way", "node" };

                    foreach (string osmElementType in elementTypes)
                    {
                        using (ComReleaser comReleaser = new ComReleaser())
                        {
                            queryFilter.WhereClause = "(" +  sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                                + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                                + sqlFormatter.SqlIdentifier("osmaction") + " = 'delete' AND "
                                + sqlFormatter.SqlIdentifier("osmelementtype") + " = '" + osmElementType + "'";

                            searchCursor = revisionTable.Search(queryFilter, false);
                            comReleaser.ManageLifetime(searchCursor);

                            searchRowToUpdate = searchCursor.NextRow();

                            if (searchRowToUpdate != null)
                            {
                                if (TrackCancel.Continue() == false)
                                {
                                    closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                    return;
                                }

                                if (uploadDelete == null)
                                {
                                    uploadDelete = new delete();
                                    listOfDeletes = new List<object>();
                                }
                            }

                            while (searchRowToUpdate != null)
                            {
                                try
                                {
                                    string action = String.Empty;
                                    if (revActionFieldIndex != -1)
                                    {
                                        action = searchRowToUpdate.get_Value(revActionFieldIndex) as string;
                                    }

                                    string elementType = String.Empty;
                                    if (revElementTypeFieldIndex != -1)
                                    {
                                        elementType = searchRowToUpdate.get_Value(revElementTypeFieldIndex) as string;
                                    }

                                    string sourceFCName = String.Empty;
                                    if (revFCNameFieldIndex != -1)
                                    {
                                        sourceFCName = searchRowToUpdate.get_Value(revFCNameFieldIndex) as string;
                                    }

                                    long osmOldID = -1;
                                    if (revOldIDFieldIndex != -1)
                                    {
                                        osmOldID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                    }

                                    int osmVersion = -1;
                                    if (revVersionFieldIndex != -1)
                                    {
                                        osmVersion = Convert.ToInt32(searchRowToUpdate.get_Value(revVersionFieldIndex));
                                    }

                                    // into multiple sets
                                    if ((featureUpdateCounter % maxElementsinChangeSet) == 0)
                                    {
                                        // add any outstanding creations to the changeset items
                                        if (listOfDeletes != null && uploadDelete != null)
                                        {
                                            uploadDelete.Items = listOfDeletes.ToArray();
                                            // in case there are any creates let's add them to the changeset document
                                            changeSetItems.Add(uploadDelete);
                                        }

                                        // add all the changeset items to the changeset document
                                        osmChangeDocument.Items = changeSetItems.ToArray();

                                        // submit changeset
                                        try
                                        {
                                            httpClient = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/changeset/" + changeSetID + "/upload") as HttpWebRequest;
                                            httpClient = OSMGPDownload.AssignProxyandCredentials(httpClient);
                                            httpClient.Method = "POST";
                                            SetBasicAuthHeader(httpClient, userCredentialGPValue.EncodedUserNamePassWord);
                                            httpClient.Timeout = secondsToTimeout * 1000;

                                            string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(osmChangeDocument, null, Encoding.UTF8, "text/xml");
                                            OsmRest.HttpUtils.Post(httpClient, sContent);

                                            httpResponse = httpClient.GetResponse() as HttpWebResponse;
                                            diffResult diffResultResonse = OsmRest.HttpUtils.GetResponse(httpResponse);

                                            // parse changes locally and update local data sources
                                            if (diffResultResonse != null)
                                            {
                                                ParseResultDiff(diffResultResonse, revisionTable, pointFeatureClass, lineFeatureClass, polygonFeatureClass, relationTable, user_displayname, userID, changeSetID, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                            }

                                        }
                                        catch (Exception ex)
                                        {
                                            closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                            message.AddError(120009, ex.Message);

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

                                            if (httpResponse != null)
                                            {
                                                httpResponse.Close();
                                            }

                                            return;
                                        }
                                        finally
                                        {
                                            // reset the list and containers of modifications for the next batch
                                            listOfDeletes.Clear();
                                            changeSetItems.Clear();

                                            if (httpResponse != null)
                                            {
                                                httpResponse.Close();
                                            }
                                        }

                                        if (TrackCancel.Continue() == false)
                                        {
                                            closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                            return;
                                        }

                                        CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                                    }

                                    switch (elementType)
                                    {
                                        case "node":
                                            IPoint deletePoint = null;
                                            if (revLongitudeFieldIndex != -1 && revLatitudeFieldIndex != -1)
                                            {
                                                try
                                                {
                                                    // let's reconstruct the delete point
                                                    deletePoint = new PointClass();
                                                    deletePoint.X = Convert.ToDouble(searchRowToUpdate.get_Value(revLongitudeFieldIndex));
                                                    deletePoint.Y = Convert.ToDouble(searchRowToUpdate.get_Value(revLatitudeFieldIndex));
                                                    deletePoint.SpatialReference = m_wgs84;
                                                }
                                                catch (Exception ex)
                                                {
                                                    message.AddWarning(ex.Message);
                                                }

                                                if (deletePoint == null)
                                                {
                                                    // inform the about the issue - no successful creation of point and continue on to the next delete instruction
                                                    // in the revision table
                                                    message.AddWarning(resourceManager.GetString("GPTools_OSMGPUpload_invalidPoint"));
                                                    searchRowToUpdate = searchCursor.NextRow();
                                                    continue;
                                                }
                                            }

                                            node deleteNode = CreateNodeRepresentation(pointFeatureClass, action, osmOldID, changeSetID, osmVersion, deletePoint, internalExtensionVersion);
                                            listOfDeletes.Add(deleteNode);
                                            break;
                                        case "way":
                                            way deleteWay = null;
                                            if (sourceFCName.Contains("_osm_ln"))
                                            {
                                                deleteWay = CreateWayRepresentation(lineFeatureClass, action, osmOldID, changeSetID, osmVersion, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                            }
                                            else if (sourceFCName.Contains("_osm_ply"))
                                            {
                                                deleteWay = CreateWayRepresentation(polygonFeatureClass, action, osmOldID, changeSetID, osmVersion, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                            }
                                            listOfDeletes.Add(deleteWay);
                                            break;
                                        case "relation":
                                            relation deleteRelation = null;
                                            if (sourceFCName.Contains("_osm_ln"))
                                            {
                                                deleteRelation = CreateRelationRepresentation((ITable)lineFeatureClass, action, osmOldID, changeSetID, osmVersion, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                            }
                                            else if (sourceFCName.Contains("_osm_ply"))
                                            {
                                                deleteRelation = CreateRelationRepresentation((ITable)polygonFeatureClass, action, osmOldID, changeSetID, osmVersion, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                            }
                                            else if (sourceFCName.Contains("_osm_relation"))
                                            {
                                                deleteRelation = CreateRelationRepresentation(relationTable, action, osmOldID, changeSetID, osmVersion, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                            }
                                            listOfDeletes.Add(deleteRelation);
                                            break;
                                        default:
                                            break;
                                    }

                                    // track the update/sync requests against the server
                                    featureUpdateCounter = featureUpdateCounter + 1;
                                }
                                catch
                                {
                                }

                                searchRowToUpdate = searchCursor.NextRow();
                            }

                        }
                    }

                    if (listOfDeletes != null && uploadDelete != null)
                    {
                        uploadDelete.Items = listOfDeletes.ToArray();
                        // in case there are any creates let's add them to the changeset document
                        changeSetItems.Add(uploadDelete);
                    }
                    #endregion

                    if (TrackCancel.Continue() == false)
                    {
                        closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                        return;
                    }

                    // add all the changeset items to the changeset document
                    osmChangeDocument.Items = changeSetItems.ToArray();

                    // submit changeset
                    try
                    {
                        httpClient = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/changeset/" + changeSetID + "/upload") as HttpWebRequest;
                        httpClient = OSMGPDownload.AssignProxyandCredentials(httpClient);
                        httpClient.Method = "POST";
                        SetBasicAuthHeader(httpClient, userCredentialGPValue.EncodedUserNamePassWord);
                        httpClient.Timeout = secondsToTimeout * 1000;

                        message.AddMessage(String.Format(resourceManager.GetString("GPTools_OSMGPUpload_featureSubmit"), featureUpdateCounter));

                        string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(osmChangeDocument, null, Encoding.UTF8, "text/xml");
                        OsmRest.HttpUtils.Post(httpClient, sContent);

                        httpResponse = httpClient.GetResponse() as HttpWebResponse;

                        //Exception with an error HTTP 400
                        diffResult diffResultResonse = OsmRest.HttpUtils.GetResponse(httpResponse);

                        message.AddMessage(resourceManager.GetString("GPTools_OSMGPUpload_updatelocalData"));

                        // parse changes locally and update local data sources
                        if (diffResultResonse != null)
                        {
                            ParseResultDiff(diffResultResonse, revisionTable, pointFeatureClass, lineFeatureClass, polygonFeatureClass, relationTable, user_displayname, userID, changeSetID, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                        }
                    }
                    catch (Exception ex)
                    {
                        message.AddError(120009, ex.Message);

                        try
                        {
                            if (ex is WebException)
                            {
                                WebException webException = ex as WebException;
                                string serverErrorMessage = webException.Response.Headers["Error"];
                                if (!String.IsNullOrEmpty(serverErrorMessage))
                                {
                                    message.AddError(120009, serverErrorMessage);
                                }
                            }
                        }
                        catch (Exception innerexception)
                        {
                            message.AddError(120009, innerexception.Message);
                        }
                    }
                    finally
                    {
                        if (httpResponse != null)
                        {
                            httpResponse.Close();
                        }
                    }
                    #endregion
                }
                else
                {
                    #region single upload format
                    #region submit the create nodes first
                    queryFilter.WhereClause = "(" +
                        sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                        + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                        + sqlFormatter.SqlIdentifier("osmaction") + " = 'create'  AND "
                        + sqlFormatter.SqlIdentifier("osmelementtype") + " = 'node'";

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        searchCursor = revisionTable.Search(queryFilter, false);
                        comReleaser.ManageLifetime(searchCursor);

                        while ((searchRowToUpdate = searchCursor.NextRow()) != null)
                        {
                            try
                            {
                                string action = String.Empty;
                                if (revActionFieldIndex != -1)
                                {
                                    action = searchRowToUpdate.get_Value(revActionFieldIndex) as string;
                                }
                                string elementType = String.Empty;
                                if (revElementTypeFieldIndex != -1)
                                {
                                    elementType = searchRowToUpdate.get_Value(revElementTypeFieldIndex) as string;
                                }

                                string sourceFCName = String.Empty;
                                if (revFCNameFieldIndex != -1)
                                {
                                    sourceFCName = searchRowToUpdate.get_Value(revFCNameFieldIndex) as string;
                                }

                                long osmOldID = -1;
                                if (revOldIDFieldIndex != -1)
                                {
                                    osmOldID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                }

                                // if the overall number of uploaded elements is too big for a single changeset we do need to split it up
                                // into multiple sets
                                if ((featureUpdateCounter % maxElementsinChangeSet) == 0)
                                {
                                    CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                                }

                                osm createNode = CreateOSMNodeRepresentation(pointFeatureClass, action, osmOldID, changeSetID, -1, null, internalExtensionVersion);

                                httpClient = null;
                                httpClient = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/" + elementType + "/create") as HttpWebRequest;
                                httpClient = OSMGPDownload.AssignProxyandCredentials(httpClient);
                                httpClient.Method = "PUT";
                                SetBasicAuthHeader(httpClient, userCredentialGPValue.EncodedUserNamePassWord);
                                httpClient.Timeout = secondsToTimeout * 1000;

                                httpResponse = null;

                                string nodeContent = OsmRest.SerializeUtils.CreateXmlSerializable(createNode, serializer, Encoding.UTF8, "text/xml");

                                if (String.IsNullOrEmpty(nodeContent))
                                {
                                    continue;
                                }

                                OsmRest.HttpUtils.Put(httpClient, nodeContent);

                                httpResponse = httpClient.GetResponse() as HttpWebResponse;

                                createNode = null;

                                // track the update/sync requests against the server
                                featureUpdateCounter = featureUpdateCounter + 1;

                                if (httpResponse != null)
                                {
                                    string newIDString = OsmRest.HttpUtils.GetResponseContent(httpResponse);

                                    nodeosmIDLookup.Add(osmOldID, Convert.ToInt64(newIDString));

                                    // update the revision table
                                    if (revNewIDFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revNewIDFieldIndex, Convert.ToString(newIDString));
                                    }
                                    if (revVersionFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revVersionFieldIndex, 1);
                                    }
                                    if (revStatusFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revStatusFieldIndex, httpResponse.StatusCode.ToString());
                                    }
                                    if (revStatusCodeFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revStatusCodeFieldIndex, (int)httpResponse.StatusCode);
                                    }
                                    if (revChangeSetIDFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revChangeSetIDFieldIndex, Convert.ToString(changeSetID));
                                    }

                                    // update the source point feature class as well
                                    updateSource((ITable)pointFeatureClass, action, osmOldID, Convert.ToInt64(newIDString), user_displayname, userID, 1, Convert.ToInt32(changeSetID), nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup,internalExtensionVersion);
                                }
                            }
                            catch (Exception ex)
                            {

                                message.AddError(120009, ex.Message);

                                if (ex is WebException)
                                {
                                    updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                }
                            }
                            finally
                            {
                                try
                                {
                                    searchRowToUpdate.Store();
                                }
                                catch (Exception ex)
                                {
                                    System.Diagnostics.Debug.WriteLine(ex.Message);
                                }

                                if (httpResponse != null)
                                {
                                    httpResponse.Close();
                                }
                            }

                            if (TrackCancel.Continue() == false)
                            {
                                closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                return;
                            }
                        }
                    }
                    #endregion

                    #region next the create ways
                    queryFilter.WhereClause = "(" +
                        sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                        + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                        + sqlFormatter.SqlIdentifier("osmaction") + " = 'create'  AND "
                        + sqlFormatter.SqlIdentifier("osmelementtype") + " = 'way'";

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        searchCursor = revisionTable.Search(queryFilter, false);
                        comReleaser.ManageLifetime(searchCursor);

                        while ((searchRowToUpdate = searchCursor.NextRow()) != null)
                        {
                            try
                            {
                                string action = String.Empty;
                                if (revActionFieldIndex != -1)
                                {
                                    action = searchRowToUpdate.get_Value(revActionFieldIndex) as string;
                                }
                                string elementType = String.Empty;
                                if (revElementTypeFieldIndex != -1)
                                {
                                    elementType = searchRowToUpdate.get_Value(revElementTypeFieldIndex) as string;
                                }

                                string sourceFCName = String.Empty;
                                if (revFCNameFieldIndex != -1)
                                {
                                    sourceFCName = searchRowToUpdate.get_Value(revFCNameFieldIndex) as string;
                                }

                                long osmOldID = -1;
                                if (revOldIDFieldIndex != -1)
                                {
                                    osmOldID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                }

                                bool isPolygon = false;
                                if (sourceFCName.IndexOf("_osm_ply") > -1)
                                {
                                    isPolygon = true;
                                }

                                // if the overall number of uploaded elements is too big for a single changeset we do need to split it up
                                // into multiple sets
                                if ((featureUpdateCounter % maxElementsinChangeSet) == 0)
                                {
                                    CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                                }

                                osm createWay = new osm();
                                if (isPolygon == false)
                                {
                                    createWay = CreateOSMWayRepresentation(lineFeatureClass, action, osmOldID, changeSetID, -1, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                }
                                else
                                {
                                    createWay = CreateOSMWayRepresentation(polygonFeatureClass, action, osmOldID, changeSetID, -1, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                }

                                try
                                {
                                    HttpWebRequest httpClient3 = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/" + elementType + "/create") as HttpWebRequest;
                                    httpClient3 = OSMGPDownload.AssignProxyandCredentials(httpClient3);
                                    httpClient3.Method = "PUT";
                                    SetBasicAuthHeader(httpClient3, userCredentialGPValue.EncodedUserNamePassWord);
                                    httpClient.Timeout = secondsToTimeout * 1000;

                                    string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(createWay, serializer, Encoding.UTF8, "text/xml");
                                    OsmRest.HttpUtils.Put(httpClient3, sContent);
                                    createWay = null;

                                    httpResponse = null;
                                    httpResponse = httpClient3.GetResponse() as HttpWebResponse;

                                    // track the update/sync requests against the server
                                    featureUpdateCounter = featureUpdateCounter + 1;
                                }
                                catch (Exception ex)
                                {
                                    message.AddError(120009, ex.Message);

                                    if (ex is WebException)
                                    {
                                        updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                    }
                                }

                                if (httpResponse != null)
                                {
                                    string newIDString = OsmRest.HttpUtils.GetResponseContent(httpResponse);

                                    wayosmIDLookup.Add(osmOldID, Convert.ToInt64(newIDString));

                                    // update the revision table
                                    if (revNewIDFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revNewIDFieldIndex, Convert.ToString(newIDString));
                                    }
                                    if (revVersionFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revVersionFieldIndex, 1);
                                    }
                                    if (revStatusFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revStatusFieldIndex, httpResponse.StatusCode.ToString());
                                    }
                                    if (revStatusCodeFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revStatusCodeFieldIndex, (int)httpResponse.StatusCode);
                                    }
                                    if (revChangeSetIDFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revChangeSetIDFieldIndex, Convert.ToString(changeSetID));
                                    }

                                    // update the source line/polygon feature class as well
                                    if (isPolygon == false)
                                    {
                                        updateSource((ITable)lineFeatureClass, action, osmOldID, Convert.ToInt64(newIDString), user_displayname, userID, 1, Convert.ToInt32(changeSetID), nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                    }
                                    else
                                    {
                                        updateSource((ITable)polygonFeatureClass, action, osmOldID, Convert.ToInt64(newIDString), user_displayname, userID, 1, Convert.ToInt32(changeSetID), nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                    }
                                }
                            }

                            catch (Exception ex)
                            {
                                message.AddError(120009, ex.Message);

                                if (ex is WebException)
                                {
                                    updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                }
                            }
                            finally
                            {
                                try
                                {
                                    searchRowToUpdate.Store();
                                }
                                catch (Exception ex)
                                {
                                    System.Diagnostics.Debug.WriteLine(ex.Message);
                                }

                                if (httpResponse != null)
                                {
                                    httpResponse.Close();
                                }
                            }

                            if (TrackCancel.Continue() == false)
                            {
                                closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);

                                return;
                            }
                        }
                    }
                    #endregion

                    #region and then create relations
                    queryFilter.WhereClause = "(" +
                        sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                        + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                        + sqlFormatter.SqlIdentifier("osmaction") + " = 'create'  AND "
                        + sqlFormatter.SqlIdentifier("osmelementtype") + " = 'relation'";

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        searchCursor = revisionTable.Search(queryFilter, false);
                        comReleaser.ManageLifetime(searchCursor);

                        while ((searchRowToUpdate = searchCursor.NextRow()) != null)
                        {
                            try
                            {

                                string action = String.Empty;
                                if (revActionFieldIndex != -1)
                                {
                                    action = searchRowToUpdate.get_Value(revActionFieldIndex) as string;
                                }
                                string elementType = String.Empty;
                                if (revElementTypeFieldIndex != -1)
                                {
                                    elementType = searchRowToUpdate.get_Value(revElementTypeFieldIndex) as string;
                                }

                                string sourceFCName = String.Empty;
                                if (revFCNameFieldIndex != -1)
                                {
                                    sourceFCName = searchRowToUpdate.get_Value(revFCNameFieldIndex) as string;
                                }

                                long osmOldID = -1;
                                if (revOldIDFieldIndex != -1)
                                {
                                    osmOldID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                }

                                bool isPolygon = false;
                                if (sourceFCName.IndexOf("_osm_ply") > -1)
                                {
                                    isPolygon = true;
                                }

                                // if the overall number of uploaded elements is too big for a single changeset we do need to split it up
                                // into multiple sets
                                if ((featureUpdateCounter % maxElementsinChangeSet) == 0)
                                {
                                    CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                                }

                                osm createRelation = null;
                                // the relation is acutally multi-part line
                                if (sourceFCName.Contains("_osm_ln"))
                                {
                                    createRelation = CreateOSMRelationRepresentation((ITable)lineFeatureClass, action, osmOldID, changeSetID, -1, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                }
                                else if (sourceFCName.Contains("_osm_ply"))
                                {
                                    createRelation = CreateOSMRelationRepresentation((ITable)polygonFeatureClass, action, osmOldID, changeSetID, -1, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                }
                                else
                                {
                                    createRelation = CreateOSMRelationRepresentation(relationTable, action, osmOldID, changeSetID, -1, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                }
                                try
                                {
                                    HttpWebRequest httpClient4 = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/" + elementType + "/create") as HttpWebRequest;
                                    httpClient4 = OSMGPDownload.AssignProxyandCredentials(httpClient4);
                                    SetBasicAuthHeader(httpClient4, userCredentialGPValue.EncodedUserNamePassWord);
                                    httpClient4.Timeout = secondsToTimeout * 1000;
                                    string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(createRelation, serializer, Encoding.UTF8, "text/xml");

                                    OsmRest.HttpUtils.Put(httpClient4, sContent);

                                    httpResponse = null;
                                    httpResponse = httpClient4.GetResponse() as HttpWebResponse;
                                    // track the update/sync requests against the server
                                    featureUpdateCounter = featureUpdateCounter + 1;
                                }
                                catch (Exception ex)
                                {
                                    message.AddError(120009, ex.Message);

                                    if (ex is WebException)
                                    {
                                        updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                    }
                                }

                                if (httpResponse != null)
                                {
                                    string newIDString = OsmRest.HttpUtils.GetResponseContent(httpResponse);

                                    relationosmIDLookup.Add(osmOldID, Convert.ToInt64(newIDString));

                                    // update the revision table
                                    if (revNewIDFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revNewIDFieldIndex, Convert.ToString(newIDString));
                                    }
                                    if (revVersionFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revVersionFieldIndex, 1);
                                    }
                                    if (revStatusFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revStatusFieldIndex, httpResponse.StatusCode.ToString());
                                    }
                                    if (revStatusCodeFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revStatusCodeFieldIndex, (int)httpResponse.StatusCode);
                                    }
                                    if (revChangeSetIDFieldIndex != -1)
                                    {
                                        searchRowToUpdate.set_Value(revChangeSetIDFieldIndex, Convert.ToInt32(changeSetID));
                                    }

                                    if (sourceFCName.Contains("_osm_ln"))
                                    {
                                        updateSource((ITable)lineFeatureClass, action, osmOldID, Convert.ToInt64(newIDString), user_displayname, userID, 1, Convert.ToInt32(changeSetID), nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                    }
                                    else if (sourceFCName.Contains("_osm_ply"))
                                    {
                                        updateSource((ITable)polygonFeatureClass, action, osmOldID, Convert.ToInt64(newIDString), user_displayname, userID, 1, Convert.ToInt32(changeSetID), nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                    }
                                    else
                                    {
                                        // update the source table holding the relation information class as well
                                        updateSource(relationTable, action, osmOldID, Convert.ToInt64(newIDString), user_displayname, userID, 1, Convert.ToInt32(changeSetID), nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                    }
                                }
                            }

                            catch (Exception ex)
                            {
                                message.AddError(120009, ex.Message);

                                if (ex is WebException)
                                {
                                    updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                }
                            }
                            finally
                            {
                                try
                                {
                                    searchRowToUpdate.Store();
                                }
                                catch (Exception ex)
                                {
                                    System.Diagnostics.Debug.WriteLine(ex.Message);
                                }
                            }

                            if (TrackCancel.Continue() == false)
                            {
                                closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                return;
                            }
                        }
                    }
                    #endregion

                    #region after that submit the modify node, way, relation
                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        queryFilter.WhereClause = "(" +
                            sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                            + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                            + sqlFormatter.SqlIdentifier("osmaction") + " = 'modify'";

                        searchCursor = revisionTable.Search(queryFilter, false);
                        comReleaser.ManageLifetime(searchCursor);

                        while ((searchRowToUpdate = searchCursor.NextRow()) != null)
                        {
                            try
                            {

                                string action = String.Empty;
                                if (revActionFieldIndex != -1)
                                {
                                    action = searchRowToUpdate.get_Value(revActionFieldIndex) as string;
                                }
                                string elementType = String.Empty;
                                if (revElementTypeFieldIndex != -1)
                                {
                                    elementType = searchRowToUpdate.get_Value(revElementTypeFieldIndex) as string;
                                }

                                string sourceFCName = String.Empty;
                                if (revFCNameFieldIndex != -1)
                                {
                                    sourceFCName = searchRowToUpdate.get_Value(revFCNameFieldIndex) as string;
                                }

                                long osmOldID = -1;
                                if (revOldIDFieldIndex != -1)
                                {
                                    osmOldID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                }

                                // if the overall number of uploaded elements is too big for a single changeset we do need to split it up
                                // into multiple sets
                                if ((featureUpdateCounter % maxElementsinChangeSet) == 0)
                                {
                                    CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                                }

                                switch (elementType)
                                {
                                    case "node":
                                        #region submit nodes to OSM server
                                        switch (action)
                                        {
                                            case "modify":
                                                long modifyID = -1;

                                                if (revNewIDFieldIndex != -1)
                                                {
                                                    object osmIDValue = searchRowToUpdate.get_Value(revNewIDFieldIndex);

                                                    if (osmIDValue == DBNull.Value)
                                                    {
                                                        osmIDValue = osmOldID;
                                                    }

                                                    try
                                                    {
                                                        modifyID = Convert.ToInt64(osmIDValue);
                                                    }
                                                    catch { }

                                                    // modifies should only happen to osm IDs > 0
                                                    // if that condition is not met let's skip this feature as something is not right
                                                    if (modifyID < 0)
                                                    {
                                                        continue;
                                                    }
                                                }

                                                int osmVersion = -1;
                                                if (revVersionFieldIndex != -1)
                                                {
                                                    osmVersion = Convert.ToInt32(searchRowToUpdate.get_Value(revVersionFieldIndex));
                                                }

                                                try
                                                {
                                                    HttpWebRequest httpClient5 = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/" + elementType + "/" + modifyID.ToString()) as HttpWebRequest;
                                                    httpClient5 = OSMGPDownload.AssignProxyandCredentials(httpClient5);
                                                    SetBasicAuthHeader(httpClient5, userCredentialGPValue.EncodedUserNamePassWord);

                                                    osm updateNode = CreateOSMNodeRepresentation(pointFeatureClass, action, modifyID, changeSetID, osmVersion, null, internalExtensionVersion);

                                                    string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(updateNode, serializer, Encoding.UTF8, "text/xml");

                                                    // if the serialized node at this time is a null or an empty string let's continue to the next point
                                                    if (String.IsNullOrEmpty(sContent))
                                                    {
                                                        continue;
                                                    }

                                                    OsmRest.HttpUtils.Put(httpClient5, sContent);

                                                    httpResponse = httpClient5.GetResponse() as HttpWebResponse;

                                                    // track the update/sync requests against the server
                                                    featureUpdateCounter = featureUpdateCounter + 1;

                                                    if (httpResponse != null)
                                                    {
                                                        string newVersionString = OsmRest.HttpUtils.GetResponseContent(httpResponse);

                                                        // update the revision table
                                                        if (revVersionFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revVersionFieldIndex, Convert.ToString(newVersionString));
                                                        }
                                                        if (revStatusFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revStatusFieldIndex, httpResponse.StatusCode.ToString());
                                                        }
                                                        if (revStatusCodeFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revStatusCodeFieldIndex, (int)httpResponse.StatusCode);
                                                        }
                                                        if (revChangeSetIDFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revChangeSetIDFieldIndex, Convert.ToInt32(changeSetID));
                                                        }

                                                        // for a modify the old id is still the new id
                                                        if (revNewIDFieldIndex != -1 && revOldIDFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revNewIDFieldIndex, searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                                        }

                                                        // update the source point feature class as well
                                                        updateSource((ITable)pointFeatureClass, action, modifyID, modifyID, user_displayname, userID, Convert.ToInt32(newVersionString), Convert.ToInt32(changeSetID), null, null, null, internalExtensionVersion);

                                                        httpResponse.Close();
                                                    }
                                                }
                                                catch (Exception ex)
                                                {
                                                    message.AddError(120009, ex.Message);

                                                    if (ex is WebException)
                                                    {
                                                        updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                                    }
                                                }

                                                break;
                                            case "delete":
                                                // the delete operations are handled separately
                                                break;
                                            default:
                                                break;
                                        }
                                        break;
                                        #endregion
                                    case "way":
                                        #region submit ways to the OSM server
                                        // determine if we have a polygon or a polyline feature class
                                        bool isPolygon = false;
                                        if (sourceFCName.IndexOf("_osm_ply") > -1)
                                        {
                                            isPolygon = true;
                                        }

                                        switch (action)
                                        {
                                            case "modify":

                                                long modifyID = -1;

                                                if (revNewIDFieldIndex != -1)
                                                {
                                                    object osmIDValue = searchRowToUpdate.get_Value(revNewIDFieldIndex);

                                                    if (osmIDValue == DBNull.Value)
                                                    {
                                                        osmIDValue = osmOldID;
                                                    }

                                                    try
                                                    {
                                                        modifyID = Convert.ToInt64(osmIDValue);
                                                    }
                                                    catch { }

                                                    // modifies should only happen to osm IDs > 0
                                                    // if that condition is not met let's skip this feature as something is not right
                                                    if (modifyID < 0)
                                                    {
                                                        continue;
                                                    }
                                                }

                                                int osmVersion = -1;
                                                if (revVersionFieldIndex != -1)
                                                {
                                                    osmVersion = Convert.ToInt32(searchRowToUpdate.get_Value(revVersionFieldIndex));
                                                }

                                                osm updateWay = new osm();
                                                if (isPolygon == false)
                                                {
                                                    updateWay = CreateOSMWayRepresentation(lineFeatureClass, action, modifyID, changeSetID, osmVersion, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                                }
                                                else
                                                {
                                                    updateWay = CreateOSMWayRepresentation(polygonFeatureClass, action, modifyID, changeSetID, osmVersion, nodeosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);
                                                }
                                                try
                                                {
                                                    string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(updateWay, serializer, Encoding.UTF8, "text/xml");
                                                    httpClient = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/" + elementType + "/" + modifyID.ToString()) as HttpWebRequest;
                                                    httpClient = OSMGPDownload.AssignProxyandCredentials(httpClient);
                                                    SetBasicAuthHeader(httpClient, userCredentialGPValue.EncodedUserNamePassWord);
                                                    OsmRest.HttpUtils.Put(httpClient, sContent);

                                                    httpResponse = httpClient.GetResponse() as HttpWebResponse;

                                                    // track the update/sync requests against the server
                                                    featureUpdateCounter = featureUpdateCounter + 1;

                                                    if (httpResponse != null)
                                                    {
                                                        string newVersionString = OsmRest.HttpUtils.GetResponseContent(httpResponse);

                                                        // update the revision table
                                                        if (revVersionFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revVersionFieldIndex, Convert.ToString(newVersionString));
                                                        }
                                                        if (revStatusFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revStatusFieldIndex, httpResponse.StatusCode.ToString());
                                                        }
                                                        if (revStatusCodeFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revStatusCodeFieldIndex, (int)httpResponse.StatusCode);
                                                        }
                                                        if (revChangeSetIDFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revChangeSetIDFieldIndex, Convert.ToInt32(changeSetID));
                                                        }

                                                        // for a modify the old id is still the new id
                                                        if (revNewIDFieldIndex != -1 && revOldIDFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revNewIDFieldIndex, searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                                        }

                                                        // update the source line/polygon feature class as well
                                                        if (isPolygon == false)
                                                        {
                                                            updateSource((ITable)lineFeatureClass, action, modifyID, modifyID, user_displayname, userID, Convert.ToInt32(newVersionString), Convert.ToInt32(changeSetID), nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                                        }
                                                        else
                                                        {
                                                            updateSource((ITable)polygonFeatureClass, action, modifyID, modifyID, user_displayname, userID, Convert.ToInt32(newVersionString), Convert.ToInt32(changeSetID), nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);
                                                        }

                                                        httpResponse.Close();
                                                    }
                                                }
                                                catch (Exception ex)
                                                {
                                                    message.AddError(120009, ex.Message);

                                                    if (ex is WebException)
                                                    {
                                                        updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                                    }
                                                }
                                                break;
                                            case "delete":
                                                // the delete operations are handled separately
                                                break;
                                            default:
                                                break;
                                        }
                                        break;
                                        #endregion
                                    case "relation":
                                        #region submit relations to the OSM server
                                        switch (action)
                                        {
                                            case "create":
                                                break;
                                            case "modify":

                                                long modifyID = -1;

                                                if (revNewIDFieldIndex != -1)
                                                {
                                                    object osmIDValue = searchRowToUpdate.get_Value(revNewIDFieldIndex);

                                                    if (osmIDValue == DBNull.Value)
                                                    {
                                                        osmIDValue = osmOldID;
                                                    }

                                                    try
                                                    {
                                                        modifyID = Convert.ToInt64(osmIDValue);
                                                    }
                                                    catch { }

                                                    // modifies should only happen to osm IDs > 0
                                                    // if that condition is not met let's skip this feature as something is not right
                                                    if (modifyID < 0)
                                                    {
                                                        continue;
                                                    }
                                                }

                                                int osmVersion = -1;
                                                if (revVersionFieldIndex != -1)
                                                {
                                                    osmVersion = Convert.ToInt32(searchRowToUpdate.get_Value(revVersionFieldIndex));
                                                }

                                                osm updateRelation = CreateOSMRelationRepresentation(relationTable, action, modifyID, changeSetID, osmVersion, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);

                                                try
                                                {
                                                    string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(updateRelation, serializer, Encoding.UTF8, "text/xml");
                                                    httpClient = HttpWebRequest.Create(baseURLGPString.Value + "/api/0.6/" + elementType + "/" + modifyID.ToString()) as HttpWebRequest;
                                                    httpClient = OSMGPDownload.AssignProxyandCredentials(httpClient);
                                                    SetBasicAuthHeader(httpClient, userCredentialGPValue.EncodedUserNamePassWord);
                                                    OsmRest.HttpUtils.Put(httpClient, sContent);

                                                    httpResponse = httpClient.GetResponse() as HttpWebResponse;

                                                    // track the update/sync requests against the server
                                                    featureUpdateCounter = featureUpdateCounter + 1;

                                                    if (httpResponse != null)
                                                    {
                                                        string newVersionString = OsmRest.HttpUtils.GetResponseContent(httpResponse);

                                                        // update the revision table
                                                        if (revVersionFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revVersionFieldIndex, Convert.ToInt32(newVersionString));
                                                        }
                                                        if (revStatusFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revStatusFieldIndex, httpResponse.StatusCode.ToString());
                                                        }
                                                        if (revStatusCodeFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revStatusCodeFieldIndex, (int)httpResponse.StatusCode);
                                                        }
                                                        if (revChangeSetIDFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revChangeSetIDFieldIndex, Convert.ToInt32(changeSetID));
                                                        }

                                                        // for a modify the old id is still the new id
                                                        if (revNewIDFieldIndex != -1 && revOldIDFieldIndex != -1)
                                                        {
                                                            searchRowToUpdate.set_Value(revNewIDFieldIndex, searchRowToUpdate.get_Value(revOldIDFieldIndex));
                                                        }

                                                        // update the source table holding the relation information class as well
                                                        updateSource(relationTable, action, modifyID, modifyID, user_displayname, userID, Convert.ToInt32(newVersionString), Convert.ToInt32(changeSetID), nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);

                                                        httpResponse.Close();
                                                    }
                                                }
                                                catch (Exception ex)
                                                {
                                                    message.AddError(120009, ex.Message);

                                                    if (ex is WebException)
                                                    {
                                                        updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                                    }
                                                }
                                                break;
                                            case "delete":
                                                // the delete operations are handled separately

                                                break;
                                            default:
                                                break;
                                        }
                                        break;
                                        #endregion
                                    default:
                                        break;
                                }
                            }

                            catch (Exception ex)
                            {
                                message.AddAbort(ex.Message);

                                if (ex is WebException)
                                {
                                    updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                }
                            }
                            finally
                            {
                                try
                                {
                                    searchRowToUpdate.Store();
                                }
                                catch (Exception ex)
                                {
                                    System.Diagnostics.Debug.WriteLine(ex.Message);
                                }

                                if (httpResponse != null)
                                {
                                    httpResponse.Close();
                                }
                            }

                            if (TrackCancel.Continue() == false)
                            {
                                closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);

                                return;
                            }

                        }
                    }
                    #endregion

                    #region now let's handle the delete in the reverse order - relation first, then ways, and then nodes as the last entity
                    #region delete relations
                    // now let's handle the delete in the reverse order - relation first, then ways, and then nodes as the last entity
                    queryFilter.WhereClause = "("
                        + sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                        + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                        + sqlFormatter.SqlIdentifier("osmaction") + " = 'delete' AND "
                        + sqlFormatter.SqlIdentifier("osmelementtype") + " = 'relation'";

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        searchCursor = revisionTable.Search(queryFilter, false);
                        comReleaser.ManageLifetime(searchCursor);

                        while ((searchRowToUpdate = searchCursor.NextRow()) != null)
                        {

                            // if the overall number of uploaded elements is too big for a single changeset we do need to split it up
                            // into multiple sets
                            if ((featureUpdateCounter % maxElementsinChangeSet) == 0)
                            {
                                CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                            }

                            long osmID = -1;
                            if (revOldIDFieldIndex != -1)
                            {
                                osmID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                            }
                            int osmVersion = -1;
                            if (revVersionFieldIndex != -1)
                            {
                                osmVersion = Convert.ToInt32(searchRowToUpdate.get_Value(revVersionFieldIndex));
                            }

                            osm deleteRelation = CreateOSMRelationRepresentation(relationTable, "delete", osmID, changeSetID, osmVersion, nodeosmIDLookup, wayosmIDLookup, relationosmIDLookup, internalExtensionVersion);

                            string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(deleteRelation, serializer, Encoding.UTF8, "text/xml");

                            string errorMessage = String.Empty;
                            try
                            {
                                httpResponse = OsmRest.HttpUtils.Delete(baseURLGPString.Value + "/api/0.6/relation/" + Convert.ToString(osmID), sContent, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout) as HttpWebResponse;

                                // track the update/sync requests against the server
                                featureUpdateCounter = featureUpdateCounter + 1;

                                if (revStatusFieldIndex != -1)
                                {
                                    searchRowToUpdate.set_Value(revStatusFieldIndex, (int)httpResponse.StatusCode);
                                }
                                if (revStatusCodeFieldIndex != -1)
                                {
                                    searchRowToUpdate.set_Value(revStatusCodeFieldIndex, (int)httpResponse.StatusCode);
                                }

                                if (httpResponse != null)
                                {
                                    httpResponse.Close();
                                }
                            }
                            catch (Exception ex)
                            {
                                message.AddError(120009, ex.Message);

                                if (ex is WebException)
                                {
                                    updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                }

                                if (httpResponse != null)
                                {
                                    httpResponse.Close();
                                }
                            }

                            try
                            {
                                searchRowToUpdate.Store();
                            }
                            catch { }

                            if (TrackCancel.Continue() == false)
                            {
                                closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                return;
                            }

                        }
                    }

                    #endregion

                    #region handle delete ways
                    queryFilter.WhereClause = "("
                        + sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                        + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                        + sqlFormatter.SqlIdentifier("osmaction") + " = 'delete' AND "
                        + sqlFormatter.SqlIdentifier("osmelementtype") + " = 'way'";

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        searchCursor = revisionTable.Search(queryFilter, false);
                        comReleaser.ManageLifetime(searchCursor);

                        while ((searchRowToUpdate = searchCursor.NextRow()) != null)
                        {

                            // if the overall number of uploaded elements is too big for a single changeset we do need to split it up
                            // into multiple sets
                            if ((featureUpdateCounter % maxElementsinChangeSet) == 0)
                            {
                                CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                            }

                            long osmID = -1;
                            if (revOldIDFieldIndex != -1)
                            {
                                osmID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                            }
                            int osmVersion = -1;
                            if (revVersionFieldIndex != -1)
                            {
                                osmVersion = Convert.ToInt32(searchRowToUpdate.get_Value(revVersionFieldIndex));
                            }

                            osm deleteWay = CreateOSMWayRepresentation(lineFeatureClass, "delete", osmID, changeSetID, osmVersion, wayosmIDLookup, pointFeatureClass, pointOSMIDFieldIndex, internalExtensionVersion);

                            string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(deleteWay, serializer, Encoding.UTF8, "text/xml");

                            try
                            {
                                httpResponse = null;
                                httpResponse = OsmRest.HttpUtils.Delete(baseURLGPString.Value + "/api/0.6/way/" + Convert.ToString(osmID), sContent, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout) as HttpWebResponse;

                                // track the update/sync requests against the server
                                featureUpdateCounter = featureUpdateCounter + 1;

                                string errorMessage = String.Empty;
                                // just grab the response and set it on the database
                                if (revStatusFieldIndex != -1)
                                {
                                    searchRowToUpdate.set_Value(revStatusFieldIndex, (int)httpResponse.StatusCode);
                                }
                                if (revStatusCodeFieldIndex != -1)
                                {
                                    searchRowToUpdate.set_Value(revStatusCodeFieldIndex, (int)httpResponse.StatusCode);
                                }

                                if (httpResponse != null)
                                {
                                    httpResponse.Close();
                                }
                            }

                            catch (Exception ex)
                            {
                                message.AddError(1200009, ex.Message);

                                if (ex is WebException)
                                {
                                    updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                }

                                if (httpResponse != null)
                                {
                                    httpResponse.Close();
                                }
                            }

                            try
                            {
                                searchRowToUpdate.Store();
                            }
                            catch { }

                            if (TrackCancel.Continue() == false)
                            {
                                closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                return;
                            }
                        }
                    }

                    #endregion

                    #region handle delete points
                    queryFilter.WhereClause = "("
                        + sqlFormatter.SqlIdentifier("osmstatuscode") + " <> 200 OR "
                        + sqlFormatter.SqlIdentifier("osmstatus") + " IS NULL) AND "
                        + sqlFormatter.SqlIdentifier("osmaction") + " = 'delete' AND "
                        + sqlFormatter.SqlIdentifier("osmelementtype") + " = 'node'";

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        searchCursor = revisionTable.Search(queryFilter, false);
                        comReleaser.ManageLifetime(searchCursor);

                        while ((searchRowToUpdate = searchCursor.NextRow()) != null)
                        {
                            // if the overall number of uploaded elements is too big for a single changeset we do need to split it up
                            // into multiple sets
                            if ((featureUpdateCounter % maxElementsinChangeSet) == 0)
                            {
                                CreateNextChangeSet(message, createChangeSetOSM, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, ref changeSetID, baseURLGPString, ref featureUpdateCounter);
                            }

                            long osmID = -1;
                            if (revOldIDFieldIndex != -1)
                            {
                                osmID = Convert.ToInt64(searchRowToUpdate.get_Value(revOldIDFieldIndex));
                            }
                            int osmVersion = -1;
                            if (revVersionFieldIndex != -1)
                            {
                                osmVersion = Convert.ToInt32(searchRowToUpdate.get_Value(revVersionFieldIndex));
                            }

                            IPoint deletePoint = null;
                            if (revLongitudeFieldIndex != -1 && revLatitudeFieldIndex != -1)
                            {
                                try
                                {
                                    // let's reconstruct the delete point
                                    deletePoint = new PointClass();
                                    deletePoint.X = Convert.ToDouble(searchRowToUpdate.get_Value(revLongitudeFieldIndex));
                                    deletePoint.Y = Convert.ToDouble(searchRowToUpdate.get_Value(revLatitudeFieldIndex));
                                    deletePoint.SpatialReference = m_wgs84;
                                }
                                catch (Exception ex)
                                {
                                    message.AddWarning(ex.Message);
                                }

                                if (deletePoint == null)
                                {
                                    // inform the about the issue - no successful creation of point and continue on to the next delete instruction
                                    // in the revision table
                                    message.AddWarning(resourceManager.GetString("GPTools_OSMGPUpload_invalidPoint"));
                                    continue;
                                }
                            }

                            osm deleteNode = CreateOSMNodeRepresentation(pointFeatureClass, "delete", osmID, changeSetID, osmVersion, deletePoint, internalExtensionVersion);

                            string sContent = OsmRest.SerializeUtils.CreateXmlSerializable(deleteNode, serializer, Encoding.UTF8, "text/xml");

                            if (String.IsNullOrEmpty(sContent))
                            {
                                continue;
                            }

                            string errorMessage = String.Empty;

                            try
                            {
                                httpResponse = OsmRest.HttpUtils.Delete(baseURLGPString.Value + "/api/0.6/node/" + Convert.ToString(osmID), sContent, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout) as HttpWebResponse;

                                if (revStatusFieldIndex != -1)
                                {
                                    searchRowToUpdate.set_Value(revStatusFieldIndex, (int)httpResponse.StatusCode);
                                }

                                if (revStatusCodeFieldIndex != -1)
                                {
                                    searchRowToUpdate.set_Value(revStatusCodeFieldIndex, (int)httpResponse.StatusCode);
                                }

                                if (httpResponse != null)
                                {
                                    httpResponse.Close();
                                }
                            }
                            catch (Exception ex)
                            {
                                message.AddError(120009, ex.Message);

                                if (ex is WebException)
                                {
                                    updateErrorStatus(message, revStatusFieldIndex, revStatusCodeFieldIndex, revErrorMessageFieldIndex, ref searchRowToUpdate, ex);
                                }

                                if (httpResponse != null)
                                {
                                    httpResponse.Close();
                                }

                            }

                            // track the update/sync requests against the server
                            featureUpdateCounter = featureUpdateCounter + 1;

                            try
                            {
                                searchRowToUpdate.Store();
                            }
                            catch { }

                            if (TrackCancel.Continue() == false)
                            {
                                closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);
                                return;
                            }
                        }
                    }

                    #endregion
                    #endregion
                    #endregion
                }
            }
            catch (Exception ex)
            {
                message.AddError(120058, ex.Message);
                message.AddError(120058, ex.StackTrace);
            }
            finally
            {
                closeChangeSet(message, userCredentialGPValue.EncodedUserNamePassWord, secondsToTimeout, changeSetID, baseURLGPString);

                if (revisionTable != null)
                {
                    try
                    {
                        ISchemaLock tableSchemaLock = revisionTable as ISchemaLock;

                        if (tableSchemaLock != null)
                        {
                            tableSchemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
                        }
                    }
                    catch (Exception eLock)
                    {
                        message.AddError(120059, resourceManager.GetString("GPTools_OSMGPUpload_LockErrorTitle") + eLock.Message);
                    }
                }

                if (revisionTable != null)
                {
                    Marshal.FinalReleaseComObject(revisionTable);
                }

                // if the searchCursor still has a reference somewhere do release it now - and as a result release any remaining table locks
                if (searchCursor != null)
                {
                    Marshal.FinalReleaseComObject(searchCursor);
                }

                gpUtilities3.RemoveInternalData();
                gpUtilities3.ReleaseInternals();

                //Marshal.ReleaseComObject(gpUtilities3);
            }
        }
        private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            string cellValueString = String.Empty;

            if (e.ColumnIndex == -1 || e.RowIndex == -1)
            {
                return;
            }


            try
            {
                // handle the event when the value in the first column changed
                // -- if an existing tag key was selected populate the 2nd column and the info 3rd column
                // -- add a new last row with the remaining tag key entries
                if (e.ColumnIndex == 0)
                {
                    Dictionary<string, ESRI.ArcGIS.OSM.OSMClassExtension.tagkey> localTags = new Dictionary<string, ESRI.ArcGIS.OSM.OSMClassExtension.tagkey>();
                    foreach (ESRI.ArcGIS.OSM.OSMClassExtension.tagkey tagKey in m_editTags.Values)
                    {
                        localTags.Add(tagKey.name, tagKey);
                    }

                    string keyValue = string.Empty;
                    // remove the once already used
                    for (int rowIndex = 0; rowIndex < dataGridView1.Rows.Count; rowIndex++)
                    {
                        keyValue = dataGridView1[0, rowIndex].Value as string;
                        if (!String.IsNullOrEmpty(keyValue))
                        {
                            if (localTags.ContainsKey(keyValue))
                            {
                                localTags.Remove(keyValue);
                            }
                        }
                    }


                    keyValue = dataGridView1[e.ColumnIndex, e.RowIndex].Value as string;
                    int deletedRow = -1;

                    // if the 
                    if (string.IsNullOrEmpty(keyValue))
                    {
                        if (!string.IsNullOrEmpty(m_ChangeTagString))
                        {
                            keyValue = m_ChangeTagString;
                            m_ChangeTagString = string.Empty;
                        }
                    }
                    else
                    {
                        try
                        {
                            deletedRow = e.RowIndex;
                            dataGridView1.Rows.RemoveAt(e.RowIndex);
                        }
                        catch
                        {

                        }
                    }

                    if (!string.IsNullOrEmpty(keyValue))
                    {
                        DataGridViewRow newRow = new DataGridViewRow();

                        // name of the tag - tag type
                        DataGridViewCell currentTagCell = new DataGridViewTextBoxCell();
                        currentTagCell.Value = keyValue;

                        // for localization include the translated language into a tooltip
                        if (m_editTags.ContainsKey(keyValue))
                        {
                            if (!String.IsNullOrEmpty(m_editTags[keyValue].displayname))
                            {
                                currentTagCell.ToolTipText = m_editTags[keyValue].displayname;
                            }
                        }

                        newRow.Cells.Insert(0, currentTagCell);

                        // the default case is not to allow the user change the key field
                        bool canEdit = false;

                        if (m_editTags.ContainsKey(keyValue))
                        {
                            if (m_editTags[keyValue].editableSpecified)
                            {
                                canEdit = m_editTags[keyValue].editable;
                            }
                        }

                        newRow.Cells[0].ReadOnly = !canEdit;


                        if (m_editTags.ContainsKey(keyValue))
                        {
                            DataGridViewCell currentValueCell = null;
                            switch (m_editTags[keyValue].tagtype)
                            {
                                case ESRI.ArcGIS.OSM.OSMClassExtension.tagkeyTagtype.tag_list:
                                    currentValueCell = new DataGridViewComboBoxCell();
                                    try
                                    {
                                        foreach (ESRI.ArcGIS.OSM.OSMClassExtension.tagvalue value in m_editTags[keyValue].tagvalue)
                                        {
                                            ((DataGridViewComboBoxCell)currentValueCell).Items.Add(value.name);
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        System.Diagnostics.Debug.WriteLine(ex.Message);
                                    }
                                    break;
                                case ESRI.ArcGIS.OSM.OSMClassExtension.tagkeyTagtype.tag_integer:
                                    currentValueCell = new DataGridViewTextBoxCell();
                                    break;
                                case ESRI.ArcGIS.OSM.OSMClassExtension.tagkeyTagtype.tag_double:
                                    currentValueCell = new DataGridViewTextBoxCell();
                                    break;
                                case ESRI.ArcGIS.OSM.OSMClassExtension.tagkeyTagtype.tag_string:
                                    currentValueCell = new DataGridViewTextBoxCell();
                                    break;
                                default:
                                    currentValueCell = new DataGridViewTextBoxCell();
                                    break;
                            }
                            try
                            {
                                newRow.Cells.Insert(1, currentValueCell);
                            }
                            catch
                            {

                            }

                            DataGridViewLinkCell currentInfoCell = new DataGridViewLinkCell();
                            currentInfoCell.LinkBehavior = LinkBehavior.SystemDefault;

                            if (m_editTags.ContainsKey(keyValue))
                            {
                                if (String.IsNullOrEmpty(m_editTags[keyValue].infoURL))
                                {
                                    currentInfoCell.Value = new Uri(m_baseInfoURI + HttpUtility.UrlEncode("Key:" + keyValue));
                                }
                                else
                                {
                                    currentInfoCell.Value = new Uri(m_editTags[keyValue].infoURL);
                                }
                            }
                            else
                            {
                                currentInfoCell.Value = new Uri(m_baseInfoURI + HttpUtility.UrlEncode("Key:" + keyValue));
                            }

                            try
                            {
                                newRow.Cells.Insert(2, currentInfoCell);
                            }
                            catch
                            {
                            }
                        }

                        dataGridView1.Rows.Add(newRow);

                        // add a new last row
                        DataGridViewRow lastRow = new DataGridViewRow();
                        DataGridViewComboBoxCell currentKeyCell = new DataGridViewComboBoxCell();
                        try
                        {
                            // show a sorted list of tags to the user
                            IEnumerable<string> sortedKeys = localTags.Keys.OrderBy(myKey => myKey);

                            foreach (string currentKey in sortedKeys)
                            {
                                currentKeyCell.Items.Add(currentKey);
                            }
                        }
                        catch { }

                        lastRow.Cells.Insert(0, currentKeyCell);

                        dataGridView1.Rows.Add(lastRow);

                        dataGridView1.FirstDisplayedScrollingRowIndex = e.RowIndex;
                        dataGridView1.Refresh();
                        dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[1];
                    }

                    return;
                }


                // ensure that we have values in the first and the second column before we commit an edit operation
                if (e.ColumnIndex == 0)
                {
                    cellValueString = dataGridView1[1, e.RowIndex].Value as string;
                }
                else if (e.ColumnIndex == 1)
                {
                    cellValueString = dataGridView1[0, e.RowIndex].Value as string;
                }

                if (String.IsNullOrEmpty(cellValueString))
                {
                    return;
                }

                if (m_editor == null)
                {
                    return;
                }

                if (((IWorkspaceEdit2)m_editor.EditWorkspace).IsInEditOperation)
                {
                }
                else
                //MessageBox.Show(resourceManager.GetString("OSMEditor_FeatureInspector_operationwarningcaption"), resourceManager.GetString("OSMClassExtension_FeatureInspector_operationwarningcaption"));
                {

                    m_editor.StartOperation();
                }

                ESRI.ArcGIS.OSM.OSMClassExtension.tag newTag = null;

                string tagString = dataGridView1[0, e.RowIndex].Value as string;
                string valueString = dataGridView1[1, e.RowIndex].Value as string;

                if (String.IsNullOrEmpty(tagString) || String.IsNullOrEmpty(valueString))
                {
                }
                else
                {
                    newTag = new ESRI.ArcGIS.OSM.OSMClassExtension.tag();
                    newTag.k = tagString;
                    newTag.v = valueString;
                }


                if (m_enumRow != null)
                {
                    m_enumRow.Reset();

                    // persist the collection in the blob/xml field
                    IFeature currentFeature = null;

                    while ((currentFeature = m_enumRow.Next() as IFeature) != null)
                    {
                        int tagCollectionFieldIndex = currentFeature.Fields.FindField("osmTags");

                        if (tagCollectionFieldIndex != -1)
                        {

                            ESRI.ArcGIS.OSM.OSMClassExtension.tag[] existingTags = _osmUtility.retrieveOSMTags((IRow)currentFeature, tagCollectionFieldIndex, m_editor.EditWorkspace);

                            if (existingTags != null)
                            {
                                // let's rebuild the tags from scratch based on the items that we found in the UI and the existing feature
                                Dictionary<string, string> existingTagsList = new Dictionary<string, string>();
                                for (int index = 0; index < existingTags.Length; index++)
                                {
                                    if (String.IsNullOrEmpty(existingTags[index].k) == false && String.IsNullOrEmpty(existingTags[index].v) == false)
                                    {
                                        existingTagsList.Add(existingTags[index].k, existingTags[index].v);
                                    }
                                }

                                if (newTag != null)
                                {
                                    if (existingTagsList.ContainsKey(newTag.k))
                                    {
                                        existingTagsList[newTag.k] = newTag.v;
                                    }
                                    else
                                    {
                                        if (!String.IsNullOrEmpty(newTag.v))
                                        {
                                            existingTagsList.Add(newTag.k, newTag.v);
                                        }
                                    }
                                }


                                int tagIndex = 0;

                                // convert the newly assembled tag list into a tag array that can be serialized into the osmtag field
                                existingTags = new ESRI.ArcGIS.OSM.OSMClassExtension.tag[existingTagsList.Count];
                                foreach (KeyValuePair<string, string> item in existingTagsList)
                                {
                                    if (!String.IsNullOrEmpty(item.Key) && !String.IsNullOrEmpty(item.Value))
                                    {
                                        ESRI.ArcGIS.OSM.OSMClassExtension.tag insertTag = new ESRI.ArcGIS.OSM.OSMClassExtension.tag();
                                        insertTag.k = item.Key;
                                        insertTag.v = item.Value;

                                        existingTags[tagIndex] = insertTag;
                                        tagIndex = tagIndex + 1;
                                    }
                                }

                                _osmUtility.insertOSMTags(tagCollectionFieldIndex, (IRow)currentFeature, existingTags, m_editor.EditWorkspace);

                                currentFeature.Store();
                            }
                        }
                    }
                }

                m_editor.StopOperation(resourceManager.GetString("OSMClassExtension_FeatureInspector_operationmenu"));

            }
            catch
            {
            }
        }
        private relation ConvertRowToOSMRelation(IRow currentRow, IWorkspace featureWorkspace, int tagsFieldIndex, int osmIDFieldIndex, int changesetIDFieldIndex, int osmVersionFieldIndex, int userIDFieldIndex, int userNameFieldIndex, int timeStampFieldIndex, int visibleFieldIndex, int membersFieldIndex, int extensionVersion)
        {

            if (currentRow == null)
                throw new ArgumentNullException("currentRow");

            relation osmRelation = new relation();
            object featureValue = DBNull.Value;
            List<object> relationItems = new List<object>();

            if (membersFieldIndex != -1)
            {
                member[] members = _osmUtility.retrieveMembers(currentRow, membersFieldIndex);
                relationItems.AddRange(members);
            }

            if (osmIDFieldIndex != -1)
            {
                osmRelation.id = Convert.ToString(currentRow.get_Value(osmIDFieldIndex));
            }

            if (changesetIDFieldIndex != -1)
            {
                featureValue = currentRow.get_Value(changesetIDFieldIndex);

                if (featureValue != DBNull.Value)
                {
                    osmRelation.changeset = Convert.ToString(currentRow.get_Value(changesetIDFieldIndex));
                }
            }

            if (osmVersionFieldIndex != -1)
            {
                featureValue = currentRow.get_Value(osmVersionFieldIndex);

                if (featureValue != DBNull.Value)
                {
                    osmRelation.version = Convert.ToString(featureValue);
                }
            }

            if (userIDFieldIndex != -1)
            {
                featureValue = currentRow.get_Value(userIDFieldIndex);

                if (featureValue != DBNull.Value)
                {
                    osmRelation.uid = Convert.ToString(featureValue);
                }
            }

            if (userNameFieldIndex != -1)
            {
                featureValue = currentRow.get_Value(userNameFieldIndex);

                if (featureValue != DBNull.Value)
                {
                    osmRelation.user = Convert.ToString(featureValue);
                }
            }

            if (timeStampFieldIndex != -1)
            {
                featureValue = currentRow.get_Value(timeStampFieldIndex);

                if (featureValue != DBNull.Value)
                {
                    osmRelation.timestamp = Convert.ToDateTime(featureValue).ToUniversalTime().ToString("u");
                }
            }

            if (visibleFieldIndex != -1)
            {
                featureValue = currentRow.get_Value(visibleFieldIndex);

                if (featureValue != DBNull.Value)
                {
                    osmRelation.visible = Convert.ToString(featureValue);
                }
            }

            if (tagsFieldIndex > -1)
            {
                tag[] tags = null;
                tags = _osmUtility.retrieveOSMTags((IRow)currentRow, tagsFieldIndex, featureWorkspace);

                // if the row is of type IFeature and a polygon then add the type=multipolygon tag
                if (currentRow is IFeature)
                {
                    IFeature currentFeature = currentRow as IFeature;

                    if (currentFeature.Shape.GeometryType == esriGeometryType.esriGeometryPolygon)
                    {
                        tag mpTag = new tag();
                        mpTag.k = "type";
                        mpTag.v = "multipolygon";

                        relationItems.Add(mpTag);
                    }
                }

                if (tags.Length != 0)
                {
                    relationItems.AddRange(tags);
                }
            }

            // add all items (member and tags) to the relation element
            osmRelation.Items = relationItems.ToArray();

            return osmRelation;
        }
        public void Execute(ESRI.ArcGIS.esriSystem.IArray paramvalues, ESRI.ArcGIS.esriSystem.ITrackCancel TrackCancel, ESRI.ArcGIS.Geoprocessing.IGPEnvironmentManager envMgr, ESRI.ArcGIS.Geodatabase.IGPMessages message)
        {
            try
            {
                IGPUtilities3 execute_Utilities = new GPUtilitiesClass();
                OSMUtility    osmUtility        = new OSMUtility();

                if (TrackCancel == null)
                {
                    TrackCancel = new CancelTrackerClass();
                }

                IGPParameter inputOSMParameter = paramvalues.get_Element(in_osmFeatureClassNumber) as IGPParameter;
                IGPValue     inputOSMGPValue   = execute_Utilities.UnpackGPValue(inputOSMParameter);

                IGPParameter  tagFieldsParameter   = paramvalues.get_Element(in_attributeSelectorNumber) as IGPParameter;
                IGPMultiValue tagCollectionGPValue = execute_Utilities.UnpackGPValue(tagFieldsParameter) as IGPMultiValue;

                if (tagCollectionGPValue == null)
                {
                    message.AddError(120048, string.Format(resourceManager.GetString("GPTools_NullPointerParameterType"), tagFieldsParameter.Name));
                    return;
                }


                IFeatureClass osmFeatureClass = null;
                ITable        osmInputTable   = null;
                IQueryFilter  osmQueryFilter  = null;

                try
                {
                    execute_Utilities.DecodeFeatureLayer(inputOSMGPValue, out osmFeatureClass, out osmQueryFilter);
                    osmInputTable = osmFeatureClass as ITable;
                }
                catch { }

                try
                {
                    if (osmInputTable == null)
                    {
                        execute_Utilities.DecodeTableView(inputOSMGPValue, out osmInputTable, out osmQueryFilter);
                    }
                }
                catch { }

                if (osmInputTable == null)
                {
                    return;
                }

                // find the field that holds tag binary/xml field
                int osmTagCollectionFieldIndex = osmInputTable.FindField("osmTags");


                // if the Field doesn't exist - wasn't found (index = -1) get out
                if (osmTagCollectionFieldIndex == -1)
                {
                    message.AddError(120005, resourceManager.GetString("GPTools_OSMGPAttributeSelector_notagfieldfound"));
                    return;
                }

                // set up the progress indicator
                IStepProgressor stepProgressor = TrackCancel as IStepProgressor;

                if (stepProgressor != null)
                {
                    int featureCount = osmInputTable.RowCount(osmQueryFilter);

                    stepProgressor.MinRange  = 0;
                    stepProgressor.MaxRange  = featureCount;
                    stepProgressor.Position  = 0;
                    stepProgressor.Message   = resourceManager.GetString("GPTools_OSMGPCombineAttributes_progressMessage");
                    stepProgressor.StepValue = 1;
                    stepProgressor.Show();
                }

                String illegalCharacters = String.Empty;

                ISQLSyntax sqlSyntax = ((IDataset)osmInputTable).Workspace as ISQLSyntax;
                if (sqlSyntax != null)
                {
                    illegalCharacters = sqlSyntax.GetInvalidCharacters();
                }

                // establish the list of field indexes only once
                Dictionary <string, int> fieldIndexes = new Dictionary <string, int>();
                for (int selectedGPValueIndex = 0; selectedGPValueIndex < tagCollectionGPValue.Count; selectedGPValueIndex++)
                {
                    // find the field index
                    int fieldIndex = osmInputTable.FindField(tagCollectionGPValue.get_Value(selectedGPValueIndex).GetAsText());

                    if (fieldIndex != -1)
                    {
                        string tagKeyName = osmInputTable.Fields.get_Field(fieldIndex).Name;

                        tagKeyName = OSMToolHelper.convert2OSMKey(tagKeyName, illegalCharacters);

                        fieldIndexes.Add(tagKeyName, fieldIndex);
                    }
                }

                ICursor updateCursor = null;
                IRow    osmRow       = null;

                using (ComReleaser comReleaser = new ComReleaser())
                {
                    updateCursor = osmInputTable.Update(osmQueryFilter, false);
                    comReleaser.ManageLifetime(updateCursor);

                    osmRow = updateCursor.NextRow();
                    int progressIndex = 0;

                    while (osmRow != null)
                    {
                        // get the current tag collection from the row
                        ESRI.ArcGIS.OSM.OSMClassExtension.tag[] osmTags = osmUtility.retrieveOSMTags(osmRow, osmTagCollectionFieldIndex, ((IDataset)osmInputTable).Workspace);

                        Dictionary <string, string> tagsDictionary = new Dictionary <string, string>();
                        for (int tagIndex = 0; tagIndex < osmTags.Length; tagIndex++)
                        {
                            tagsDictionary.Add(osmTags[tagIndex].k, osmTags[tagIndex].v);
                        }

                        // look if the tag needs to be updated or added
                        bool tagsUpdated = false;
                        foreach (var fieldItem in fieldIndexes)
                        {
                            object fldValue = osmRow.get_Value(fieldItem.Value);
                            if (fldValue != System.DBNull.Value)
                            {
                                if (tagsDictionary.ContainsKey(fieldItem.Key))
                                {
                                    if (!tagsDictionary[fieldItem.Key].Equals(fldValue))
                                    {
                                        tagsDictionary[fieldItem.Key] = Convert.ToString(fldValue);
                                        tagsUpdated = true;
                                    }
                                }
                                else
                                {
                                    tagsDictionary.Add(fieldItem.Key, Convert.ToString(fldValue));
                                    tagsUpdated = true;
                                }
                            }
                            else
                            {
                                if (tagsDictionary.ContainsKey(fieldItem.Key))
                                {
                                    tagsDictionary.Remove(fieldItem.Key);
                                    tagsUpdated = true;
                                }
                            }
                        }

                        if (tagsUpdated)
                        {
                            List <ESRI.ArcGIS.OSM.OSMClassExtension.tag> updatedTags = new List <ESRI.ArcGIS.OSM.OSMClassExtension.tag>();

                            foreach (var tagItem in tagsDictionary)
                            {
                                ESRI.ArcGIS.OSM.OSMClassExtension.tag newTag = new ESRI.ArcGIS.OSM.OSMClassExtension.tag();
                                newTag.k = tagItem.Key;
                                newTag.v = tagItem.Value;
                                updatedTags.Add(newTag);
                            }

                            // insert the tags back into the collection field
                            if (updatedTags.Count != 0)
                            {
                                osmUtility.insertOSMTags(osmTagCollectionFieldIndex, osmRow, updatedTags.ToArray(), ((IDataset)osmInputTable).Workspace);

                                updateCursor.UpdateRow(osmRow);
                            }
                        }

                        progressIndex++;
                        if (stepProgressor != null)
                        {
                            stepProgressor.Position = progressIndex;
                        }

                        if (osmRow != null)
                        {
                            Marshal.ReleaseComObject(osmRow);
                        }

                        osmRow = updateCursor.NextRow();
                    }

                    if (stepProgressor != null)
                    {
                        stepProgressor.Hide();
                    }
                }
            }
            catch (Exception ex)
            {
                message.AddError(120007, ex.Message);
            }
        }
        public void Execute(ESRI.ArcGIS.esriSystem.IArray paramvalues, ESRI.ArcGIS.esriSystem.ITrackCancel TrackCancel, ESRI.ArcGIS.Geoprocessing.IGPEnvironmentManager envMgr, ESRI.ArcGIS.Geodatabase.IGPMessages message)
        {
            try
            {
                IGPUtilities3 execute_Utilities = new GPUtilitiesClass();
                OSMUtility osmUtility = new OSMUtility();

                if (TrackCancel == null)
                {
                    TrackCancel = new CancelTrackerClass();
                }

                IGPParameter inputOSMParameter = paramvalues.get_Element(in_osmFeatureClassNumber) as IGPParameter;
                IGPValue inputOSMGPValue = execute_Utilities.UnpackGPValue(inputOSMParameter);

                IGPParameter tagFieldsParameter = paramvalues.get_Element(in_attributeSelectorNumber) as IGPParameter;
                IGPMultiValue tagCollectionGPValue = execute_Utilities.UnpackGPValue(tagFieldsParameter) as IGPMultiValue;

                if (tagCollectionGPValue == null)
                {
                    message.AddError(120048, string.Format(resourceManager.GetString("GPTools_NullPointerParameterType"), tagFieldsParameter.Name));
                    return;
                }

                IFeatureClass osmFeatureClass = null;
                ITable osmInputTable = null;
                IQueryFilter osmQueryFilter = null;

                try
                {
                    execute_Utilities.DecodeFeatureLayer(inputOSMGPValue, out osmFeatureClass, out osmQueryFilter);
                    osmInputTable = osmFeatureClass as ITable;
                }
                catch { }

                try
                {
                    if (osmInputTable == null)
                    {
                        execute_Utilities.DecodeTableView(inputOSMGPValue, out osmInputTable, out osmQueryFilter);
                    }
                }
                catch { }

                if (osmInputTable == null)
                {
                    return;
                }

                // find the field that holds tag binary/xml field
                int osmTagCollectionFieldIndex = osmInputTable.FindField("osmTags");

                // if the Field doesn't exist - wasn't found (index = -1) get out
                if (osmTagCollectionFieldIndex == -1)
                {
                    message.AddError(120005, resourceManager.GetString("GPTools_OSMGPAttributeSelector_notagfieldfound"));
                    return;
                }

                // set up the progress indicator
                IStepProgressor stepProgressor = TrackCancel as IStepProgressor;

                if (stepProgressor != null)
                {
                    int featureCount = osmInputTable.RowCount(osmQueryFilter);

                    stepProgressor.MinRange = 0;
                    stepProgressor.MaxRange = featureCount;
                    stepProgressor.Position = 0;
                    stepProgressor.Message = resourceManager.GetString("GPTools_OSMGPCombineAttributes_progressMessage");
                    stepProgressor.StepValue = 1;
                    stepProgressor.Show();
                }

                String illegalCharacters = String.Empty;

                ISQLSyntax sqlSyntax = ((IDataset)osmInputTable).Workspace as ISQLSyntax;
                if (sqlSyntax != null)
                {
                    illegalCharacters = sqlSyntax.GetInvalidCharacters();
                }

                // establish the list of field indexes only once
                Dictionary<string, int> fieldIndexes = new Dictionary<string, int>();
                for (int selectedGPValueIndex = 0; selectedGPValueIndex < tagCollectionGPValue.Count; selectedGPValueIndex++)
                {
                    // find the field index
                    int fieldIndex = osmInputTable.FindField(tagCollectionGPValue.get_Value(selectedGPValueIndex).GetAsText());

                    if (fieldIndex != -1)
                    {
                        string tagKeyName = osmInputTable.Fields.get_Field(fieldIndex).Name;

                        tagKeyName = OSMToolHelper.convert2OSMKey(tagKeyName, illegalCharacters);

                        fieldIndexes.Add(tagKeyName, fieldIndex);
                    }
                }

                ICursor updateCursor = null;
                IRow osmRow = null;

                using (ComReleaser comReleaser = new ComReleaser())
                {
                    updateCursor = osmInputTable.Update(osmQueryFilter, false);
                    comReleaser.ManageLifetime(updateCursor);

                    osmRow = updateCursor.NextRow();
                    int progressIndex = 0;

                    while (osmRow != null)
                    {
                        // get the current tag collection from the row
                        ESRI.ArcGIS.OSM.OSMClassExtension.tag[] osmTags = osmUtility.retrieveOSMTags(osmRow, osmTagCollectionFieldIndex, ((IDataset)osmInputTable).Workspace);

                        Dictionary<string, string> tagsDictionary = new Dictionary<string, string>();
                        for (int tagIndex = 0; tagIndex < osmTags.Length; tagIndex++)
                        {
                            tagsDictionary.Add(osmTags[tagIndex].k, osmTags[tagIndex].v);
                        }

                        // look if the tag needs to be updated or added
                        bool tagsUpdated = false;
                        foreach (var fieldItem in fieldIndexes)
                        {
                            object fldValue = osmRow.get_Value(fieldItem.Value);
                            if (fldValue != System.DBNull.Value)
                            {
                                if (tagsDictionary.ContainsKey(fieldItem.Key))
                                {
                                    if (!tagsDictionary[fieldItem.Key].Equals(fldValue))
                                    {
                                        tagsDictionary[fieldItem.Key] = Convert.ToString(fldValue);
                                        tagsUpdated = true;
                                    }
                                }
                                else
                                {
                                    tagsDictionary.Add(fieldItem.Key, Convert.ToString(fldValue));
                                    tagsUpdated = true;
                                }
                            }
                        }

                        if (tagsUpdated)
                        {
                            List<ESRI.ArcGIS.OSM.OSMClassExtension.tag> updatedTags = new List<ESRI.ArcGIS.OSM.OSMClassExtension.tag>();

                            foreach (var tagItem in tagsDictionary)
                            {
                                ESRI.ArcGIS.OSM.OSMClassExtension.tag newTag = new ESRI.ArcGIS.OSM.OSMClassExtension.tag();
                                newTag.k = tagItem.Key;
                                newTag.v = tagItem.Value;
                                updatedTags.Add(newTag);
                            }

                            // insert the tags back into the collection field
                            if (updatedTags.Count != 0)
                            {
                                osmUtility.insertOSMTags(osmTagCollectionFieldIndex, osmRow, updatedTags.ToArray(), ((IDataset)osmInputTable).Workspace);

                                updateCursor.UpdateRow(osmRow);
                            }
                        }

                        progressIndex++;
                        if (stepProgressor != null)
                        {
                            stepProgressor.Position = progressIndex;
                        }

                        if (osmRow != null)
                            Marshal.ReleaseComObject(osmRow);

                        osmRow = updateCursor.NextRow();
                    }

                    if (stepProgressor != null)
                    {
                        stepProgressor.Hide();
                    }
                }
            }
            catch (Exception ex)
            {
                message.AddError(120007, ex.Message);
            }
        }
        public static bool IsThisWayALine(way currentway)
        {
            bool isALine = true;

            try
            {
                if (currentway.nd != null)
                {
                    if (currentway.nd[0].@ref == currentway.nd[currentway.nd.Length - 1].@ref)
                    {
                        isALine = false;
                    }
                    else
                    {
                        isALine = true;
                    }
                }

                // coastlines are special cases and we will accept them as lines only
                bool isCoastline = false;

                if (currentway.tag != null)
                {
                    tag coastlineTag = new tag();
                    coastlineTag.k = "natural";
                    coastlineTag.v = "coastline";

                    tag areaTag = new tag();
                    areaTag.k = "area";
                    areaTag.v = "yes";

                    tag highwayTag = new tag();
                    highwayTag.k = "highway";
                    highwayTag.v = "something";

                    if (currentway.tag.Contains(coastlineTag, new TagKeyValueComparer()))
                    {
                        isCoastline = true;
                        isALine = true;
                    }

                    if (currentway.tag.Contains(highwayTag, new TagKeyComparer()))
                    {
                        isALine = true;
                    }

                    if (currentway.tag.Contains(areaTag, new TagKeyValueComparer()))
                    {
                        if (isCoastline == false)
                        {
                            isALine = false;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                System.Diagnostics.Debug.WriteLine(ex.StackTrace);
            }

            return isALine;
        }
        private void insertTags(Dictionary<string, int> domainAttributeFieldIndices, Dictionary<string, int> domainAttributeFieldLength, int tagCollectionFieldIndex, IRowBuffer row, tag[] tagsToInsert)
        {
            Dictionary<string, object> tagGdbStorageValues = new Dictionary<string, object>(domainAttributeFieldIndices.Count);
            foreach (var item in domainAttributeFieldIndices)
            {
                tagGdbStorageValues[item.Key] = null;
            }

            if (tagsToInsert != null)
            {
                foreach (tag tagItem in tagsToInsert)
                {
                    if (domainAttributeFieldIndices.ContainsKey(tagItem.k))
                    {
                        if (tagItem.v.Length <= domainAttributeFieldLength[tagItem.k])
                        {
                            tagGdbStorageValues[tagItem.k] = tagItem.v;
                        }
                    }
                }
            }

            foreach (var item in domainAttributeFieldIndices)
            {
                row.set_Value(item.Value, tagGdbStorageValues[item.Key]);
            }

            if (tagCollectionFieldIndex > -1)
            {
                _osmUtility.insertOSMTags(tagCollectionFieldIndex, row, tagsToInsert);
            }

            tagGdbStorageValues.Clear();
            tagGdbStorageValues = null;
        }