///<summary>Simple helper to create a featureclass in a geodatabase.</summary>
        /// 
        ///<param name="workspace">An IWorkspace2 interface</param>
        ///<param name="featureDataset">An IFeatureDataset interface or Nothing</param>
        ///<param name="featureClassName">A System.String that contains the name of the feature class to open or create. Example: "states"</param>
        ///<param name="fields">An IFields interface</param>
        ///<param name="CLSID">A UID value or Nothing. Example "esriGeoDatabase.Feature" or Nothing</param>
        ///<param name="CLSEXT">A UID value or Nothing (this is the class extension if you want to reference a class extension when creating the feature class).</param>
        ///<param name="strConfigKeyword">An empty System.String or RDBMS table string for ArcSDE. Example: "myTable" or ""</param>
        ///  
        ///<returns>An IFeatureClass interface or a Nothing</returns>
        ///  
        ///<remarks>
        ///  (1) If a 'featureClassName' already exists in the workspace a reference to that feature class 
        ///      object will be returned.
        ///  (2) If an IFeatureDataset is passed in for the 'featureDataset' argument the feature class
        ///      will be created in the dataset. If a Nothing is passed in for the 'featureDataset'
        ///      argument the feature class will be created in the workspace.
        ///  (3) When creating a feature class in a dataset the spatial reference is inherited 
        ///      from the dataset object.
        ///  (4) If an IFields interface is supplied for the 'fields' collection it will be used to create the
        ///      table. If a Nothing value is supplied for the 'fields' collection, a table will be created using 
        ///      default values in the method.
        ///  (5) The 'strConfigurationKeyword' parameter allows the application to control the physical layout 
        ///      for this table in the underlying RDBMS—for example, in the case of an Oracle database, the 
        ///      configuration keyword controls the tablespace in which the table is created, the initial and 
        ///     next extents, and other properties. The 'strConfigurationKeywords' for an ArcSDE instance are 
        ///      set up by the ArcSDE data administrator, the list of available keywords supported by a workspace 
        ///      may be obtained using the IWorkspaceConfiguration interface. For more information on configuration 
        ///      keywords, refer to the ArcSDE documentation. When not using an ArcSDE table use an empty 
        ///      string (ex: "").
        ///</remarks>
        internal ESRI.ArcGIS.Geodatabase.IFeatureClass CreatePolygonFeatureClass(ESRI.ArcGIS.Geodatabase.IWorkspace2 workspace, ESRI.ArcGIS.Geodatabase.IFeatureDataset featureDataset, System.String featureClassName, ESRI.ArcGIS.Geodatabase.IFields fields, ESRI.ArcGIS.esriSystem.UID CLSID, ESRI.ArcGIS.esriSystem.UID CLSEXT, System.String strConfigKeyword, OSMDomains osmDomains, string metadataAbstract, string metadataPurpose)
        {
            if (featureClassName == "") return null; // name was not passed in

            ESRI.ArcGIS.Geodatabase.IFeatureClass featureClass = null;

            try
            {

                ESRI.ArcGIS.Geodatabase.IFeatureWorkspace featureWorkspace = (ESRI.ArcGIS.Geodatabase.IFeatureWorkspace)workspace; // Explicit Cast

                if (workspace.get_NameExists(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTFeatureClass, featureClassName)) //feature class with that name already exists
                {
                    // if a feature class with the same name already exists delete it....
                    featureClass = featureWorkspace.OpenFeatureClass(featureClassName);

                    if (!DeleteDataset((IDataset)featureClass))
                    {
                        return featureClass;
                    }
                }

                // assign the class id value if not assigned
                if (CLSID == null)
                {
                    CLSID = new ESRI.ArcGIS.esriSystem.UIDClass();
                    CLSID.Value = "esriGeoDatabase.Feature";
                }

                ESRI.ArcGIS.Geodatabase.IObjectClassDescription objectClassDescription = new ESRI.ArcGIS.Geodatabase.FeatureClassDescriptionClass();

                // if a fields collection is not passed in then supply our own
                if (fields == null)
                {
                    // create the fields using the required fields method
                    fields = objectClassDescription.RequiredFields;
                    ESRI.ArcGIS.Geodatabase.IFieldsEdit fieldsEdit = (ESRI.ArcGIS.Geodatabase.IFieldsEdit)fields; // Explicit Cast

                    // add the domain driven string field for the OSM features
                    foreach (var domainAttribute in osmDomains.domain)
                    {
                        IFieldEdit domainField = new FieldClass() as IFieldEdit;
                        domainField.Name_2 = domainAttribute.name;
                        domainField.Type_2 = esriFieldType.esriFieldTypeString;
                        domainField.Required_2 = true;
                        domainField.Length_2 = 30;
                        try
                        {
                            domainField.Domain_2 = ((IWorkspaceDomains)workspace).get_DomainByName(domainAttribute.name + "_ply");
                        }
                        catch (Exception ex)
                        {
                            System.Diagnostics.Debug.WriteLine(ex.Message);
                            System.Diagnostics.Debug.WriteLine(ex.StackTrace);
                        }

                        fieldsEdit.AddField((IField)domainField);
                    }

                    // add the OSM ID field
                    IFieldEdit osmIDField = new FieldClass() as IFieldEdit;
                    osmIDField.Name_2 = "OSMID";
                    osmIDField.Type_2 = esriFieldType.esriFieldTypeString;
                    osmIDField.Length_2 = 20;
                    osmIDField.Required_2 = true;
                    fieldsEdit.AddField((IField)osmIDField);

                    // add the field for the tag cloud for all other tag/value pairs
                    IFieldEdit osmXmlTagsField = new FieldClass() as IFieldEdit;
                    osmXmlTagsField.Name_2 = "osmTags";
                    osmXmlTagsField.Required_2 = true;
                    //if (((IWorkspace)workspace).Type == esriWorkspaceType.esriLocalDatabaseWorkspace)
                    //{
                    osmXmlTagsField.Type_2 = esriFieldType.esriFieldTypeBlob;
                    //}
                    //else
                    //{
                    //    osmXmlTagsField.Type_2 = esriFieldType.esriFieldTypeXML;
                    //}
                    fieldsEdit.AddField((IField)osmXmlTagsField);

                    // user, uid, visible, version, changeset, timestamp
                    IFieldEdit osmuserField = new FieldClass() as IFieldEdit;
                    osmuserField.Name_2 = "osmuser";
                    osmuserField.Type_2 = esriFieldType.esriFieldTypeString;
                    osmuserField.Required_2 = true;
                    osmuserField.Length_2 = 100;
                    fieldsEdit.AddField((IField)osmuserField);

                    IFieldEdit osmuidField = new FieldClass() as IFieldEdit;
                    osmuidField.Name_2 = "osmuid";
                    osmuidField.Required_2 = true;
                    osmuidField.Type_2 = esriFieldType.esriFieldTypeInteger;
                    fieldsEdit.AddField((IField)osmuidField);

                    IFieldEdit osmvisibleField = new FieldClass() as IFieldEdit;
                    osmvisibleField.Name_2 = "osmvisible";
                    osmvisibleField.Required_2 = true;
                    osmvisibleField.Type_2 = esriFieldType.esriFieldTypeString;
                    osmvisibleField.Length_2 = 20;
                    fieldsEdit.AddField((IField)osmvisibleField);

                    IFieldEdit osmversionField = new FieldClass() as IFieldEdit;
                    osmversionField.Name_2 = "osmversion";
                    osmversionField.Required_2 = true;
                    osmversionField.Type_2 = esriFieldType.esriFieldTypeSmallInteger;
                    fieldsEdit.AddField((IField)osmversionField);

                    IFieldEdit osmchangesetField = new FieldClass() as IFieldEdit;
                    osmchangesetField.Name_2 = "osmchangeset";
                    osmchangesetField.Required_2 = true;
                    osmchangesetField.Type_2 = esriFieldType.esriFieldTypeInteger;
                    fieldsEdit.AddField((IField)osmchangesetField);

                    IFieldEdit osmtimestampField = new FieldClass() as IFieldEdit;
                    osmtimestampField.Name_2 = "osmtimestamp";
                    osmtimestampField.Required_2 = true;
                    osmtimestampField.Type_2 = esriFieldType.esriFieldTypeDate;
                    fieldsEdit.AddField((IField)osmtimestampField);

                    IFieldEdit osmrelationIDField = new FieldClass() as IFieldEdit;
                    osmrelationIDField.Name_2 = "osmMemberOf";
                    osmrelationIDField.Required_2 = true;
                    //if (((IWorkspace)workspace).Type == esriWorkspaceType.esriLocalDatabaseWorkspace)
                    //{
                    osmrelationIDField.Type_2 = esriFieldType.esriFieldTypeBlob;
                    //}
                    //else
                    //{
                    //    osmrelationIDField.Type_2 = esriFieldType.esriFieldTypeXML;
                    //}
                    fieldsEdit.AddField((IField)osmrelationIDField);

                    //IFieldEdit osmrelationsField = new FieldClass() as IFieldEdit;
                    //osmrelationsField.Name_2 = "osmMembers";
                    //if (((IWorkspace)workspace).Type == esriWorkspaceType.esriLocalDatabaseWorkspace)
                    //{
                    //    osmrelationsField.Type_2 = esriFieldType.esriFieldTypeBlob;
                    //}
                    //else
                    //{
                    //    osmrelationsField.Type_2 = esriFieldType.esriFieldTypeXML;
                    //}
                    //fieldsEdit.AddField((IField)osmrelationsField);
                    IFieldEdit osmSupportingElementField = new FieldClass() as IFieldEdit;
                    osmSupportingElementField.Name_2 = "osmSupportingElement";
                    osmSupportingElementField.Type_2 = esriFieldType.esriFieldTypeString;
                    osmSupportingElementField.Length_2 = 5;
                    osmSupportingElementField.DefaultValue_2 = "no";
                    osmSupportingElementField.Required_2 = true;
                    fieldsEdit.AddField((IField)osmSupportingElementField);

                    IFieldEdit osmMembersField = new FieldClass() as IFieldEdit;
                    osmMembersField.Name_2 = "osmMembers";
                    //if (((IWorkspace)workspace).Type == esriWorkspaceType.esriLocalDatabaseWorkspace)
                    //{
                    osmMembersField.Type_2 = esriFieldType.esriFieldTypeBlob;
                    osmMembersField.Required_2 = true;
                    //}
                    //else
                    //{
                    //    osmMembersField.Type_2 = esriFieldType.esriFieldTypeXML;
                    //}
                    fieldsEdit.AddField((IField)osmMembersField);

                    //IFieldEdit osmTrackChangesField = new FieldClass() as IFieldEdit;
                    //osmTrackChangesField.Name_2 = "osmTrackChanges";
                    //osmTrackChangesField.Required_2 = true;
                    //osmTrackChangesField.Type_2 = esriFieldType.esriFieldTypeSmallInteger;
                    //osmTrackChangesField.DefaultValue_2 = 0;
                    //fieldsEdit.AddField((IField)osmTrackChangesField);

                    fields = (ESRI.ArcGIS.Geodatabase.IFields)fieldsEdit; // Explicit Cast
                }

                System.String strShapeField = "";

                // locate the shape field
                for (int j = 0; j < fields.FieldCount; j++)
                {
                    if (fields.get_Field(j).Type == ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry)
                    {
                        strShapeField = fields.get_Field(j).Name;

                        // redefine geometry type

                        IFieldEdit shapeField = fields.get_Field(j) as IFieldEdit;
                        IGeometryDefEdit geometryDef = new GeometryDefClass() as IGeometryDefEdit;
                        geometryDef.GeometryType_2 = esriGeometryType.esriGeometryPolygon;
                        geometryDef.HasZ_2 = false;
                        geometryDef.HasM_2 = false;
                        geometryDef.GridCount_2 = 1;
                        geometryDef.set_GridSize(0, 0);

                        geometryDef.SpatialReference_2 = ((IGeoDataset)featureDataset).SpatialReference;

                        shapeField.GeometryDef_2 = (IGeometryDef)geometryDef;

                        break;
                    }
                }

                // Use IFieldChecker to create a validated fields collection.
                ESRI.ArcGIS.Geodatabase.IFieldChecker fieldChecker = new ESRI.ArcGIS.Geodatabase.FieldCheckerClass();
                ESRI.ArcGIS.Geodatabase.IEnumFieldError enumFieldError = null;
                ESRI.ArcGIS.Geodatabase.IFields validatedFields = null;
                fieldChecker.ValidateWorkspace = (ESRI.ArcGIS.Geodatabase.IWorkspace)workspace;
                fieldChecker.Validate(fields, out enumFieldError, out validatedFields);

                // The enumFieldError enumerator can be inspected at this point to determine
                // which fields were modified during validation.

                // finally create and return the feature class
                if (featureDataset == null)// if no feature dataset passed in, create at the workspace level
                {
                    featureClass = featureWorkspace.CreateFeatureClass(featureClassName, validatedFields, CLSID, CLSEXT, ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimple, strShapeField, strConfigKeyword);
                    IPropertySet extensionPropertySet = new PropertySetClass();
                    extensionPropertySet.SetProperty("VERSION", OSMClassExtensionManager.Version);
                    ((IClassSchemaEdit2)featureClass).AlterClassExtensionProperties(extensionPropertySet);

                }
                else
                {
                    featureClass = featureDataset.CreateFeatureClass(featureClassName, validatedFields, CLSID, CLSEXT, ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimple, strShapeField, strConfigKeyword);
                    IPropertySet extensionPropertySet = new PropertySetClass();
                    extensionPropertySet.SetProperty("VERSION", OSMClassExtensionManager.Version);
                    ((IClassSchemaEdit2)featureClass).AlterClassExtensionProperties(extensionPropertySet);
                }

                // create the openstreetmap spcific metadata
                _osmUtility.CreateOSMMetadata((IDataset)featureClass, metadataAbstract, metadataPurpose);

                // the change at release 2.1 requires a new model name
                IModelInfo fcModelInfo = featureClass as IModelInfo;
                if (fcModelInfo != null)
                {
                    fcModelInfo.ModelName = OSMClassExtensionManager.OSMModelName;
                }

            }
            catch
            {
                throw;
            }

            return featureClass;
        }
        internal List<string> loadOSMRelations(string osmFileLocation, ref ITrackCancel TrackCancel, ref IGPMessages message, IGPValue targetGPValue, IFeatureClass osmPointFeatureClass, IFeatureClass osmLineFeatureClass, IFeatureClass osmPolygonFeatureClass, int relationCapacity, ITable relationTable, OSMDomains availableDomains, bool fastLoad, bool checkForExisting)
        {
            List<string> missingRelations = null;
            XmlReader osmFileXmlReader = null;
            XmlSerializer relationSerializer = null;

            try
            {

                missingRelations = new List<string>();

                if (osmLineFeatureClass == null)
                {
                    throw new ArgumentNullException("osmLineFeatureClass");
                }

                if (osmPolygonFeatureClass == null)
                {
                    throw new ArgumentNullException("osmPolygonFeatureClass");
                }

                if (relationTable == null)
                {
                    throw new ArgumentNullException("relationTable");
                }

                int osmPointIDFieldIndex = osmPointFeatureClass.FindField("OSMID");
                Dictionary<string, int> osmPointDomainAttributeFieldIndices = new Dictionary<string, int>();
                foreach (var domains in availableDomains.domain)
                {
                    int currentFieldIndex = osmPointFeatureClass.FindField(domains.name);

                    if (currentFieldIndex != -1)
                    {
                        osmPointDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex);
                    }
                }
                int tagCollectionPointFieldIndex = osmPointFeatureClass.FindField("osmTags");
                int osmUserPointFieldIndex = osmPointFeatureClass.FindField("osmuser");
                int osmUIDPointFieldIndex = osmPointFeatureClass.FindField("osmuid");
                int osmVisiblePointFieldIndex = osmPointFeatureClass.FindField("osmvisible");
                int osmVersionPointFieldIndex = osmPointFeatureClass.FindField("osmversion");
                int osmChangesetPointFieldIndex = osmPointFeatureClass.FindField("osmchangeset");
                int osmTimeStampPointFieldIndex = osmPointFeatureClass.FindField("osmtimestamp");
                int osmMemberOfPointFieldIndex = osmPointFeatureClass.FindField("osmMemberOf");
                int osmSupportingElementPointFieldIndex = osmPointFeatureClass.FindField("osmSupportingElement");
                int osmWayRefCountFieldIndex = osmPointFeatureClass.FindField("wayRefCount");

                int osmLineIDFieldIndex = osmLineFeatureClass.FindField("OSMID");
                Dictionary<string, int> osmLineDomainAttributeFieldIndices = new Dictionary<string, int>();
                Dictionary<string, int> osmLineDomainAttributeFieldLength = new Dictionary<string, int>();
                foreach (var domains in availableDomains.domain)
                {
                    int currentFieldIndex = osmLineFeatureClass.FindField(domains.name);

                    if (currentFieldIndex != -1)
                    {
                        osmLineDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex);
                        osmLineDomainAttributeFieldLength.Add(domains.name, osmLineFeatureClass.Fields.get_Field(currentFieldIndex).Length);
                    }
                }
                int tagCollectionPolylineFieldIndex = osmLineFeatureClass.FindField("osmTags");
                int osmUserPolylineFieldIndex = osmLineFeatureClass.FindField("osmuser");
                int osmUIDPolylineFieldIndex = osmLineFeatureClass.FindField("osmuid");
                int osmVisiblePolylineFieldIndex = osmLineFeatureClass.FindField("osmvisible");
                int osmVersionPolylineFieldIndex = osmLineFeatureClass.FindField("osmversion");
                int osmChangesetPolylineFieldIndex = osmLineFeatureClass.FindField("osmchangeset");
                int osmTimeStampPolylineFieldIndex = osmLineFeatureClass.FindField("osmtimestamp");
                int osmMemberOfPolylineFieldIndex = osmLineFeatureClass.FindField("osmMemberOf");
                int osmMembersPolylineFieldIndex = osmLineFeatureClass.FindField("osmMembers");
                int osmSupportingElementPolylineFieldIndex = osmLineFeatureClass.FindField("osmSupportingElement");

                int osmPolygonIDFieldIndex = osmPolygonFeatureClass.FindField("OSMID");
                Dictionary<string, int> osmPolygonDomainAttributeFieldIndices = new Dictionary<string, int>();
                Dictionary<string, int> osmPolygonDomainAttributeFieldLength = new Dictionary<string, int>();
                foreach (var domains in availableDomains.domain)
                {
                    int currentFieldIndex = osmPolygonFeatureClass.FindField(domains.name);

                    if (currentFieldIndex != -1)
                    {
                        osmPolygonDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex);
                        osmPolygonDomainAttributeFieldLength.Add(domains.name, osmPolygonFeatureClass.Fields.get_Field(currentFieldIndex).Length);
                    }
                }
                int tagCollectionPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmTags");
                int osmUserPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmuser");
                int osmUIDPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmuid");
                int osmVisiblePolygonFieldIndex = osmPolygonFeatureClass.FindField("osmvisible");
                int osmVersionPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmversion");
                int osmChangesetPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmchangeset");
                int osmTimeStampPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmtimestamp");
                int osmMemberOfPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmMemberOf");
                int osmMembersPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmMembers");
                int osmSupportingElementPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmSupportingElement");

                int osmRelationIDFieldIndex = relationTable.FindField("OSMID");
                int tagCollectionRelationFieldIndex = relationTable.FindField("osmTags");
                int osmUserRelationFieldIndex = relationTable.FindField("osmuser");
                int osmUIDRelationFieldIndex = relationTable.FindField("osmuid");
                int osmVisibleRelationFieldIndex = relationTable.FindField("osmvisible");
                int osmVersionRelationFieldIndex = relationTable.FindField("osmversion");
                int osmChangesetRelationFieldIndex = relationTable.FindField("osmchangeset");
                int osmTimeStampRelationFieldIndex = relationTable.FindField("osmtimestamp");
                int osmMemberOfRelationFieldIndex = relationTable.FindField("osmMemberOf");
                int osmMembersRelationFieldIndex = relationTable.FindField("osmMembers");
                int osmSupportingElementRelationFieldIndex = relationTable.FindField("osmSupportingElement");

                // list for reference count and relation list for lines/polygons/relations
                // set up the progress indicator
                IStepProgressor stepProgressor = TrackCancel as IStepProgressor;

                if (stepProgressor != null)
                {
                    stepProgressor.MinRange = 0;
                    stepProgressor.MaxRange = relationCapacity;
                    stepProgressor.Position = 0;
                    stepProgressor.Message = _resourceManager.GetString("GPTools_OSMGPFileReader_loadingRelations");
                    stepProgressor.StepValue = 1;
                    stepProgressor.Show();
                }

                bool relationIndexRebuildRequired = false;

                if (relationTable != null)
                {
                    osmFileXmlReader = System.Xml.XmlReader.Create(osmFileLocation);
                    relationSerializer = new XmlSerializer(typeof(relation));

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        using (SchemaLockManager linelock = new SchemaLockManager(osmLineFeatureClass as ITable), polygonLock = new SchemaLockManager(osmPolygonFeatureClass as ITable), relationLock = new SchemaLockManager(relationTable))
                        {
                            ICursor rowCursor = relationTable.Insert(true);
                            comReleaser.ManageLifetime(rowCursor);

                            IRowBuffer rowBuffer = relationTable.CreateRowBuffer();
                            comReleaser.ManageLifetime(rowBuffer);

                            IFeatureCursor lineFeatureInsertCursor = osmLineFeatureClass.Insert(true);
                            comReleaser.ManageLifetime(lineFeatureInsertCursor);

                            IFeatureBuffer lineFeatureBuffer = osmLineFeatureClass.CreateFeatureBuffer();
                            comReleaser.ManageLifetime(lineFeatureBuffer);

                            IFeatureCursor polygonFeatureInsertCursor = osmPolygonFeatureClass.Insert(true);
                            comReleaser.ManageLifetime(polygonFeatureInsertCursor);

                            IFeatureBuffer polygonFeatureBuffer = osmPolygonFeatureClass.CreateFeatureBuffer();
                            comReleaser.ManageLifetime(polygonFeatureBuffer);

                            int relationCount = 1;
                            int relationDebugCount = 1;

                            string lineSQLIdentifier = osmLineFeatureClass.SqlIdentifier("OSMID");
                            string polygonSQLIdentifier = osmPolygonFeatureClass.SqlIdentifier("OSMID");

                            message.AddMessage(_resourceManager.GetString("GPTools_OSMGPFileReader_resolvegeometries"));

                            osmFileXmlReader.MoveToContent();
                            while (osmFileXmlReader.Read())
                            {
                                if (osmFileXmlReader.IsStartElement())
                                {
                                    if (osmFileXmlReader.Name == "relation")
                                    {
                                        relation currentRelation = null;
                                        try
                                        {
                                            // read the full relation node
                                            string currentrelationString = osmFileXmlReader.ReadOuterXml();

                                            using (StringReader relationReader = new System.IO.StringReader(currentrelationString))
                                            {
                                                // de-serialize the xml into to the class instance
                                                currentRelation = relationSerializer.Deserialize(relationReader) as relation;
                                            }

                                            if (currentRelation == null)
                                                continue;

                                            relationDebugCount = relationDebugCount + 1;
                                            esriGeometryType detectedGeometryType = determineRelationGeometryType(osmLineFeatureClass, osmPolygonFeatureClass, relationTable, currentRelation);

                                            if (checkForExisting)
                                            {
                                                switch (detectedGeometryType)
                                                {
                                                    case esriGeometryType.esriGeometryAny:
                                                        if (CheckIfExists(relationTable, currentRelation.id))
                                                            continue;
                                                        break;
                                                    case esriGeometryType.esriGeometryBag:
                                                        if (CheckIfExists(relationTable, currentRelation.id))
                                                            continue;
                                                        break;
                                                    case esriGeometryType.esriGeometryBezier3Curve:
                                                        break;
                                                    case esriGeometryType.esriGeometryCircularArc:
                                                        break;
                                                    case esriGeometryType.esriGeometryEllipticArc:
                                                        break;
                                                    case esriGeometryType.esriGeometryEnvelope:
                                                        break;
                                                    case esriGeometryType.esriGeometryLine:
                                                        if (CheckIfExists(osmLineFeatureClass as ITable, currentRelation.id))
                                                            continue;
                                                        break;
                                                    case esriGeometryType.esriGeometryMultiPatch:
                                                        break;
                                                    case esriGeometryType.esriGeometryMultipoint:
                                                        break;
                                                    case esriGeometryType.esriGeometryNull:
                                                        if (CheckIfExists(relationTable, currentRelation.id))
                                                            continue;
                                                        break;
                                                    case esriGeometryType.esriGeometryPath:
                                                        break;
                                                    case esriGeometryType.esriGeometryPoint:
                                                        break;
                                                    case esriGeometryType.esriGeometryPolygon:
                                                        if (CheckIfExists(osmPolygonFeatureClass as ITable, currentRelation.id))
                                                            continue;
                                                        break;
                                                    case esriGeometryType.esriGeometryPolyline:
                                                        if (CheckIfExists(osmLineFeatureClass as ITable, currentRelation.id))
                                                            continue;
                                                        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;
                                                }
                                            }

                                            List<tag> relationTagList = new List<tag>();
                                            List<member> relationMemberList = new List<member>();
                                            Dictionary<string, string> wayList = new Dictionary<string, string>();

                                            // sanity check that the overall relation notation contains at least something
                                            if (currentRelation.Items == null)
                                                continue;

                                            List<OSMNodeFeature> osmPointList = null;
                                            List<OSMLineFeature> osmLineList = null;
                                            List<OSMPolygonFeature> osmPolygonList = null;
                                            List<OSMRelation> osmRelationList = null;

                                            rowBuffer = relationTable.CreateRowBuffer();
                                            comReleaser.ManageLifetime(rowBuffer);

                                            lineFeatureBuffer = osmLineFeatureClass.CreateFeatureBuffer();
                                            comReleaser.ManageLifetime(lineFeatureBuffer);

                                            polygonFeatureBuffer = osmPolygonFeatureClass.CreateFeatureBuffer();
                                            comReleaser.ManageLifetime(polygonFeatureBuffer);

                                            foreach (var item in currentRelation.Items)
                                            {
                                                if (item is member)
                                                {
                                                    member memberItem = item as member;
                                                    relationMemberList.Add(memberItem);

                                                    switch (memberItem.type)
                                                    {
                                                        case memberType.way:

                                                            if (!wayList.ContainsKey(memberItem.@ref))
                                                                wayList.Add(memberItem.@ref, memberItem.role);

                                                            if (IsThisWayALine(memberItem.@ref, osmLineFeatureClass, lineSQLIdentifier, osmPolygonFeatureClass, polygonSQLIdentifier))
                                                            {
                                                                if (osmLineList == null)
                                                                {
                                                                    osmLineList = new List<OSMLineFeature>();
                                                                }

                                                                OSMLineFeature lineFeature = new OSMLineFeature();
                                                                lineFeature.relationList = new List<string>();
                                                                lineFeature.lineID = memberItem.@ref;

                                                                if (detectedGeometryType == esriGeometryType.esriGeometryPolygon)
                                                                {
                                                                    lineFeature.relationList.Add(currentRelation.id + "_ply");
                                                                }
                                                                else if (detectedGeometryType == esriGeometryType.esriGeometryPolyline)
                                                                {
                                                                    lineFeature.relationList.Add(currentRelation.id + "_ln");
                                                                }
                                                                else
                                                                {
                                                                    lineFeature.relationList.Add(currentRelation.id + "_rel");
                                                                }

                                                                osmLineList.Add(lineFeature);
                                                            }
                                                            else
                                                            {
                                                                if (osmPolygonList == null)
                                                                {
                                                                    osmPolygonList = new List<OSMPolygonFeature>();
                                                                }

                                                                OSMPolygonFeature polygonFeature = new OSMPolygonFeature();
                                                                polygonFeature.relationList = new List<string>();
                                                                polygonFeature.polygonID = memberItem.@ref;

                                                                if (detectedGeometryType == esriGeometryType.esriGeometryPolygon)
                                                                {
                                                                    polygonFeature.relationList.Add(currentRelation.id + "_ply");
                                                                }
                                                                else if (detectedGeometryType == esriGeometryType.esriGeometryPolyline)
                                                                {
                                                                    polygonFeature.relationList.Add(currentRelation.id + "_ln");
                                                                }
                                                                else
                                                                {
                                                                    polygonFeature.relationList.Add(currentRelation.id + "_rel");
                                                                }

                                                                osmPolygonList.Add(polygonFeature);
                                                            }

                                                            break;
                                                        case memberType.node:

                                                            if (osmPointList == null)
                                                            {
                                                                osmPointList = new List<OSMNodeFeature>();
                                                            }

                                                            OSMNodeFeature nodeFeature = new OSMNodeFeature();
                                                            nodeFeature.relationList = new List<string>();
                                                            nodeFeature.nodeID = memberItem.@ref;

                                                            nodeFeature.relationList.Add(currentRelation.id + "_rel");

                                                            osmPointList.Add(nodeFeature);

                                                            break;
                                                        case memberType.relation:

                                                            if (osmRelationList == null)
                                                            {
                                                                osmRelationList = new List<OSMRelation>();
                                                            }

                                                            OSMRelation relation = new OSMRelation();
                                                            relation.relationList = new List<string>();
                                                            relation.relationID = memberItem.@ref;
                                                            relation.relationList.Add(currentRelation.id + "_rel");

                                                            break;
                                                        default:
                                                            break;
                                                    }

                                                }
                                                else if (item is tag)
                                                {
                                                    relationTagList.Add((tag)item);
                                                }
                                            }

                                            // if there is a defined geometry type use it to generate a multipart geometry
                                            if (detectedGeometryType == esriGeometryType.esriGeometryPolygon)
                                            {
                                                #region create multipart polygon geometry
                                                //IFeature mpFeature = osmPolygonFeatureClass.CreateFeature();

                                                IPolygon relationMPPolygon = new PolygonClass();
                                                relationMPPolygon.SpatialReference = ((IGeoDataset)osmPolygonFeatureClass).SpatialReference;

                                                ISegmentCollection relationPolygonGeometryCollection = relationMPPolygon as ISegmentCollection;

                                                IQueryFilter osmIDQueryFilter = new QueryFilterClass();
                                                string sqlPolyOSMID = osmPolygonFeatureClass.SqlIdentifier("OSMID");
                                                object missing = Type.Missing;
                                                bool relationComplete = true;

                                                // loop through the list of referenced ways that are listed in a relation
                                                // for each of the items we need to make a decision if they have merit to qualify as stand-alone features
                                                // due to the presence of meaningful attributes (tags)
                                                foreach (KeyValuePair<string, string> wayKey in wayList)
                                                {
                                                    if (relationComplete == false)
                                                        break;

                                                    if (TrackCancel.Continue() == false)
                                                    {
                                                        return missingRelations;
                                                    }

                                                    osmIDQueryFilter.WhereClause = sqlPolyOSMID + " = '" + wayKey.Key + "'";

                                                    System.Diagnostics.Debug.WriteLine("Relation (Polygon) #: " + relationDebugCount + " :___: " + currentRelation.id + " :___: " + wayKey.Key);

                                                    using (ComReleaser relationComReleaser = new ComReleaser())
                                                    {
                                                        IFeatureCursor featureCursor = osmPolygonFeatureClass.Search(osmIDQueryFilter, false);
                                                        relationComReleaser.ManageLifetime(featureCursor);

                                                        IFeature partFeature = featureCursor.NextFeature();

                                                        // set the appropriate field attribute to become invisible as a standalone features
                                                        if (partFeature != null)
                                                        {
                                                            IGeometryCollection ringCollection = partFeature.Shape as IGeometryCollection;

                                                            // test for available content in the geometry collection
                                                            if (ringCollection.GeometryCount > 0)
                                                            {
                                                                // test if we dealing with a valid geometry
                                                                if (ringCollection.get_Geometry(0).IsEmpty == false)
                                                                {
                                                                    // add it to the new geometry and mark the added geometry as a supporting element
                                                                    relationPolygonGeometryCollection.AddSegmentCollection((ISegmentCollection)ringCollection.get_Geometry(0));

                                                                    if (osmSupportingElementPolygonFieldIndex > -1)
                                                                    {
                                                                        // if the member of a relation has the role of "inner" and it has tags, then let's keep it
                                                                        // as a standalone feature as well
                                                                        // the geometry is then a hole in the relation but due to the tags it also has merits to be
                                                                        // considered a stand-alone feature
                                                                        if (wayKey.Value.ToLower().Equals("inner"))
                                                                        {
                                                                            if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolygonFieldIndex, null))
                                                                            {
                                                                                partFeature.set_Value(osmSupportingElementPolygonFieldIndex, "yes");
                                                                            }
                                                                        }
                                                                        else
                                                                        {
                                                                            // relation member without an explicit role or the role of "outer" are turned into
                                                                            // supporting features if they don't have relevant attribute
                                                                            if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolylineFieldIndex, null))
                                                                            {
                                                                                partFeature.set_Value(osmSupportingElementPolygonFieldIndex, "yes");
                                                                            }
                                                                        }
                                                                    }

                                                                    partFeature.Store();
                                                                }
                                                            }
                                                        }
                                                        else
                                                        {
                                                            // it still can be a line geometry that will be pieced together into a polygon
                                                            IFeatureCursor lineFeatureCursor = osmLineFeatureClass.Search(osmIDQueryFilter, false);
                                                            relationComReleaser.ManageLifetime(lineFeatureCursor);

                                                            partFeature = lineFeatureCursor.NextFeature();

                                                            if (partFeature != null)
                                                            {
                                                                IGeometryCollection ringCollection = partFeature.Shape as IGeometryCollection;

                                                                // test for available content in the geometry collection
                                                                if (ringCollection.GeometryCount > 0)
                                                                {
                                                                    // test if we dealing with a valid geometry
                                                                    if (ringCollection.get_Geometry(0).IsEmpty == false)
                                                                    {
                                                                        // add it to the new geometry and mark the added geometry as a supporting element
                                                                        relationPolygonGeometryCollection.AddSegmentCollection((ISegmentCollection)ringCollection.get_Geometry(0));

                                                                        if (osmSupportingElementPolylineFieldIndex > -1)
                                                                        {
                                                                            // if the member of a relation has the role of "inner" and it has tags, then let's keep it
                                                                            // as a standalone feature as well
                                                                            // the geometry is then a hole in the relation but due to the tags it also has merits to be
                                                                            // considered a stand-alone feature
                                                                            if (wayKey.Value.ToLower().Equals("inner"))
                                                                            {
                                                                                if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolylineFieldIndex, null))
                                                                                {
                                                                                    partFeature.set_Value(osmSupportingElementPolylineFieldIndex, "yes");
                                                                                }
                                                                            }
                                                                            else
                                                                            {
                                                                                // relation member without an explicit role or the role of "outer" are turned into
                                                                                // supporting features if they don't have relevant attribute
                                                                                if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolylineFieldIndex, null))
                                                                                {
                                                                                    partFeature.set_Value(osmSupportingElementPolylineFieldIndex, "yes");
                                                                                }
                                                                            }
                                                                        }

                                                                        partFeature.Store();
                                                                    }
                                                                }
                                                            }
                                                            else
                                                            {
                                                                relationComplete = false;
                                                                continue;
                                                            }
                                                        }
                                                    }
                                                }

                                                // mark the relation as incomplete
                                                if (relationComplete == false)
                                                {
                                                    missingRelations.Add(currentRelation.id);
                                                    continue;
                                                }

                                                // transform the added collections for geometries into a topological correct geometry representation
                                                ((IPolygon4)relationMPPolygon).SimplifyEx(true, false, true);

                                                polygonFeatureBuffer.Shape = relationMPPolygon;

                                                if (_osmUtility.DoesHaveKeys(currentRelation))
                                                {
                                                }
                                                else
                                                {
                                                    relationTagList = MergeTagsFromOuterPolygonToRelation(currentRelation, osmPolygonFeatureClass);
                                                }

                                                insertTags(osmPolygonDomainAttributeFieldIndices, osmPolygonDomainAttributeFieldLength, tagCollectionPolygonFieldIndex, polygonFeatureBuffer, relationTagList.ToArray());

                                                if (fastLoad == false)
                                                {
                                                    if (osmMembersPolygonFieldIndex > -1)
                                                    {
                                                        _osmUtility.insertMembers(osmMembersPolygonFieldIndex, (IFeature)polygonFeatureBuffer, relationMemberList.ToArray());
                                                    }

                                                    // store the administrative attributes
                                                    // user, uid, version, changeset, timestamp, visible
                                                    if (osmUserPolygonFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.user))
                                                        {
                                                            polygonFeatureBuffer.set_Value(osmUserPolygonFieldIndex, currentRelation.user);
                                                        }
                                                    }

                                                    if (osmUIDPolygonFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.uid))
                                                        {
                                                            polygonFeatureBuffer.set_Value(osmUIDPolygonFieldIndex, Convert.ToInt32(currentRelation.uid));
                                                        }
                                                    }

                                                    if (osmVisiblePolygonFieldIndex != -1)
                                                    {
                                                        if (String.IsNullOrEmpty(currentRelation.visible) == false)
                                                        {
                                                            polygonFeatureBuffer.set_Value(osmVisiblePolygonFieldIndex, currentRelation.visible.ToString());
                                                        }
                                                        else
                                                        {
                                                            polygonFeatureBuffer.set_Value(osmVisiblePolygonFieldIndex, "unknown");
                                                        }
                                                    }

                                                    if (osmVersionPolygonFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.version))
                                                        {
                                                            polygonFeatureBuffer.set_Value(osmVersionPolygonFieldIndex, Convert.ToInt32(currentRelation.version));
                                                        }
                                                    }

                                                    if (osmChangesetPolygonFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.changeset))
                                                        {
                                                            polygonFeatureBuffer.set_Value(osmChangesetPolygonFieldIndex, Convert.ToInt32(currentRelation.changeset));
                                                        }
                                                    }

                                                    if (osmTimeStampPolygonFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.timestamp))
                                                        {
                                                            polygonFeatureBuffer.set_Value(osmTimeStampPolygonFieldIndex, Convert.ToDateTime(currentRelation.timestamp));
                                                        }
                                                    }

                                                    if (osmPolygonIDFieldIndex != -1)
                                                    {
                                                        polygonFeatureBuffer.set_Value(osmPolygonIDFieldIndex, currentRelation.id);
                                                    }

                                                    if (osmSupportingElementPolygonFieldIndex > -1)
                                                    {
                                                        polygonFeatureBuffer.set_Value(osmSupportingElementPolygonFieldIndex, "no");
                                                    }
                                                }

                                                try
                                                {
                                                    //mpFeature.Store();
                                                    polygonFeatureInsertCursor.InsertFeature(polygonFeatureBuffer);
                                                }
                                                catch (Exception ex)
                                                {
                                                    message.AddWarning(ex.Message);
                                                }
                                                #endregion
                                            }
                                            else if (detectedGeometryType == esriGeometryType.esriGeometryPolyline)
                                            {
                                                #region create multipart polyline geometry
                                                //IFeature mpFeature = osmLineFeatureClass.CreateFeature();

                                                IPolyline relationMPPolyline = new PolylineClass();
                                                relationMPPolyline.SpatialReference = ((IGeoDataset)osmLineFeatureClass).SpatialReference;

                                                IGeometryCollection relationPolylineGeometryCollection = relationMPPolyline as IGeometryCollection;

                                                IQueryFilter osmIDQueryFilter = new QueryFilterClass();
                                                object missing = Type.Missing;

                                                // loop through the
                                                foreach (KeyValuePair<string, string> wayKey in wayList)
                                                {
                                                    if (TrackCancel.Continue() == false)
                                                    {
                                                        return missingRelations;
                                                    }

                                                    osmIDQueryFilter.WhereClause = osmLineFeatureClass.WhereClauseByExtensionVersion(wayKey.Key, "OSMID", 2);

                                                    System.Diagnostics.Debug.WriteLine("Relation (Polyline) #: " + relationDebugCount + " :___: " + currentRelation.id + " :___: " + wayKey);

                                                    using (ComReleaser relationComReleaser = new ComReleaser())
                                                    {
                                                        IFeatureCursor featureCursor = osmLineFeatureClass.Search(osmIDQueryFilter, false);
                                                        relationComReleaser.ManageLifetime(featureCursor);

                                                        IFeature partFeature = featureCursor.NextFeature();

                                                        // set the appropriate field attribute to become invisible as a standalone features
                                                        if (partFeature != null)
                                                        {
                                                            if (partFeature.Shape.IsEmpty == false)
                                                            {
                                                                IGeometryCollection pathCollection = partFeature.Shape as IGeometryCollection;
                                                                relationPolylineGeometryCollection.AddGeometry(pathCollection.get_Geometry(0), ref missing, ref missing);

                                                                if (osmSupportingElementPolylineFieldIndex > -1)
                                                                {
                                                                    if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolylineFieldIndex, null))
                                                                    {
                                                                        partFeature.set_Value(osmSupportingElementPolylineFieldIndex, "yes");
                                                                    }
                                                                }

                                                                partFeature.Store();
                                                            }
                                                        }
                                                    }
                                                }

                                                lineFeatureBuffer.Shape = relationMPPolyline;

                                                insertTags(osmLineDomainAttributeFieldIndices, osmLineDomainAttributeFieldLength, tagCollectionPolylineFieldIndex, lineFeatureBuffer, relationTagList.ToArray());

                                                if (fastLoad == false)
                                                {
                                                    if (osmMembersPolylineFieldIndex > -1)
                                                    {
                                                        _osmUtility.insertMembers(osmMembersPolylineFieldIndex, (IFeature)lineFeatureBuffer, relationMemberList.ToArray());
                                                    }

                                                    // store the administrative attributes
                                                    // user, uid, version, changeset, timestamp, visible
                                                    if (osmUserPolylineFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.user))
                                                        {
                                                            lineFeatureBuffer.set_Value(osmUserPolylineFieldIndex, currentRelation.user);
                                                        }
                                                    }

                                                    if (osmUIDPolylineFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.uid))
                                                        {
                                                            lineFeatureBuffer.set_Value(osmUIDPolylineFieldIndex, Convert.ToInt32(currentRelation.uid));
                                                        }
                                                    }

                                                    if (osmVisiblePolylineFieldIndex != -1)
                                                    {
                                                        if (String.IsNullOrEmpty(currentRelation.visible) == false)
                                                        {
                                                            lineFeatureBuffer.set_Value(osmVisiblePolylineFieldIndex, currentRelation.visible.ToString());
                                                        }
                                                        else
                                                        {
                                                            lineFeatureBuffer.set_Value(osmVisiblePolylineFieldIndex, "unknown");
                                                        }
                                                    }

                                                    if (osmVersionPolylineFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.version))
                                                        {
                                                            lineFeatureBuffer.set_Value(osmVersionPolylineFieldIndex, Convert.ToInt32(currentRelation.version));
                                                        }
                                                    }

                                                    if (osmChangesetPolylineFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.changeset))
                                                        {
                                                            lineFeatureBuffer.set_Value(osmChangesetPolylineFieldIndex, Convert.ToInt32(currentRelation.changeset));
                                                        }
                                                    }

                                                    if (osmTimeStampPolylineFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.timestamp))
                                                        {
                                                            lineFeatureBuffer.set_Value(osmTimeStampPolylineFieldIndex, Convert.ToDateTime(currentRelation.timestamp));
                                                        }
                                                    }

                                                    if (osmLineIDFieldIndex != -1)
                                                    {
                                                        lineFeatureBuffer.set_Value(osmLineIDFieldIndex, currentRelation.id);
                                                    }

                                                    if (osmSupportingElementPolylineFieldIndex > -1)
                                                    {
                                                        lineFeatureBuffer.set_Value(osmSupportingElementPolylineFieldIndex, "no");
                                                    }
                                                }

                                                try
                                                {
                                                    lineFeatureInsertCursor.InsertFeature(lineFeatureBuffer);
                                                }
                                                catch (Exception ex)
                                                {
                                                    message.AddWarning(ex.Message);
                                                }
                                                #endregion

                                            }
                                            else if (detectedGeometryType == esriGeometryType.esriGeometryPoint)
                                            {
                                                System.Diagnostics.Debug.WriteLine("Relation #: " + relationDebugCount + " :____: POINT!!!");

                                                if (TrackCancel.Continue() == false)
                                                {
                                                    return missingRelations;
                                                }
                                            }
                                            else
                                            // otherwise it is relation that needs to be dealt with separately
                                            {
                                                if (TrackCancel.Continue() == false)
                                                {
                                                    return missingRelations;
                                                }

                                                System.Diagnostics.Debug.WriteLine("Relation #: " + relationDebugCount + " :____: Kept as relation");

                                                if (tagCollectionRelationFieldIndex != -1)
                                                {
                                                    _osmUtility.insertOSMTags(tagCollectionRelationFieldIndex, rowBuffer, relationTagList.ToArray());
                                                }

                                                if (fastLoad == false)
                                                {
                                                    if (osmMembersRelationFieldIndex != -1)
                                                    {
                                                        _osmUtility.insertMembers(osmMembersRelationFieldIndex, rowBuffer, relationMemberList.ToArray());
                                                    }

                                                    // store the administrative attributes
                                                    // user, uid, version, changeset, timestamp, visible
                                                    if (osmUserRelationFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.user))
                                                        {
                                                            rowBuffer.set_Value(osmUserRelationFieldIndex, currentRelation.user);
                                                        }
                                                    }

                                                    if (osmUIDRelationFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.uid))
                                                        {
                                                            rowBuffer.set_Value(osmUIDRelationFieldIndex, Convert.ToInt64(currentRelation.uid));
                                                        }
                                                    }

                                                    if (osmVisibleRelationFieldIndex != -1)
                                                    {
                                                        if (currentRelation.visible != null)
                                                        {
                                                            rowBuffer.set_Value(osmVisibleRelationFieldIndex, currentRelation.visible.ToString());
                                                        }
                                                    }

                                                    if (osmVersionRelationFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.version))
                                                        {
                                                            rowBuffer.set_Value(osmVersionRelationFieldIndex, Convert.ToInt32(currentRelation.version));
                                                        }
                                                    }

                                                    if (osmChangesetRelationFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.changeset))
                                                        {
                                                            rowBuffer.set_Value(osmChangesetRelationFieldIndex, Convert.ToInt32(currentRelation.changeset));
                                                        }
                                                    }

                                                    if (osmTimeStampRelationFieldIndex != -1)
                                                    {
                                                        if (!String.IsNullOrEmpty(currentRelation.timestamp))
                                                        {
                                                            try
                                                            {
                                                                rowBuffer.set_Value(osmTimeStampRelationFieldIndex, Convert.ToDateTime(currentRelation.timestamp));
                                                            }
                                                            catch (Exception ex)
                                                            {
                                                                message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_invalidTimeFormat"), ex.Message));
                                                            }
                                                        }
                                                    }

                                                    if (osmRelationIDFieldIndex != -1)
                                                    {
                                                        rowBuffer.set_Value(osmRelationIDFieldIndex, currentRelation.id);
                                                    }
                                                }

                                                try
                                                {
                                                    rowCursor.InsertRow(rowBuffer);
                                                    relationCount = relationCount + 1;

                                                    relationIndexRebuildRequired = true;
                                                }
                                                catch (Exception ex)
                                                {
                                                    System.Diagnostics.Debug.WriteLine(ex.Message);
                                                }

                                                // check for user interruption
                                                if (TrackCancel.Continue() == false)
                                                {
                                                    return missingRelations;
                                                }
                                            }

                                            // update the isMemberOf fields of the attached features
                                            if (osmPointList != null)
                                            {
                                                foreach (OSMNodeFeature nodeFeature in osmPointList)
                                                {
                                                    updateIsMemberOf(osmLineFeatureClass, osmMemberOfPolylineFieldIndex, nodeFeature.nodeID, nodeFeature.relationList);
                                                }
                                            }

                                            if (osmLineList != null)
                                            {
                                                foreach (OSMLineFeature lineFeature in osmLineList)
                                                {
                                                    updateIsMemberOf(osmLineFeatureClass, osmMemberOfPolylineFieldIndex, lineFeature.lineID, lineFeature.relationList);
                                                }
                                            }

                                            if (osmPolygonList != null)
                                            {
                                                foreach (OSMPolygonFeature polygonFeature in osmPolygonList)
                                                {
                                                    updateIsMemberOf(osmLineFeatureClass, osmMemberOfPolylineFieldIndex, polygonFeature.polygonID, polygonFeature.relationList);
                                                }
                                            }

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

                                            if ((relationCount % 50000) == 0)
                                            {
                                                message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_relationsloaded"), relationCount));
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            message.AddWarning(ex.Message);
                                        }
                                        finally
                                        {
                                            if (rowBuffer != null)
                                            {
                                                Marshal.ReleaseComObject(rowBuffer);

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

                                                if (lineFeatureBuffer != null)
                                                    lineFeatureBuffer = null;
                                            }

                                            if (polygonFeatureBuffer != null)
                                            {
                                                Marshal.ReleaseComObject(polygonFeatureBuffer);

                                                if (polygonFeatureBuffer != null)
                                                    polygonFeatureBuffer = null;
                                            }

                                            currentRelation = null;
                                        }
                                    }
                                }
                            }

                            // close the OSM file
                            osmFileXmlReader.Close();

                            // flush any remaining entities from the cursor
                            rowCursor.Flush();
                            polygonFeatureInsertCursor.Flush();
                            lineFeatureInsertCursor.Flush();

                            // force a garbage collection
                            System.GC.Collect();

                            // let the user know that we are done dealing with the relations
                            message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_relationsloaded"), relationCount));
                        }
                    }

                    if (stepProgressor != null)
                    {
                        stepProgressor.Hide();
                    }

                    // Addd index for osmid column as well
                    IGeoProcessor2 geoProcessor = new GeoProcessorClass();
                    bool storedOriginalLocal = geoProcessor.AddOutputsToMap;
                    IGPUtilities3 gpUtilities3 = new GPUtilitiesClass();

                    try
                    {
                        geoProcessor.AddOutputsToMap = false;

                        if (relationIndexRebuildRequired)
                        {
                            IIndexes tableIndexes = relationTable.Indexes;
                            int indexPosition = -1;
                            tableIndexes.FindIndex("osmID_IDX", out indexPosition);

                            if (indexPosition == -1)
                            {
                                IGPValue relationTableGPValue = gpUtilities3.MakeGPValueFromObject(relationTable);
                                string sddd = targetGPValue.GetAsText();
                                string tableLocation = GetLocationString(targetGPValue, relationTable);
                                IVariantArray parameterArrary = CreateAddIndexParameterArray(tableLocation, "OSMID", "osmID_IDX", "UNIQUE", "");
                                IGeoProcessorResult2 gpResults2 = geoProcessor.Execute("AddIndex_management", parameterArrary, TrackCancel) as IGeoProcessorResult2;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        message.AddWarning(ex.Message);
                    }
                    finally
                    {
                        geoProcessor.AddOutputsToMap = storedOriginalLocal;

                        Marshal.FinalReleaseComObject(gpUtilities3);
                        Marshal.FinalReleaseComObject(geoProcessor);
                    }
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                if (relationSerializer != null)
                    relationSerializer = null;

                if (osmFileXmlReader != null)
                    osmFileXmlReader = null;

                System.GC.Collect();
                System.GC.WaitForPendingFinalizers();
            }

            return missingRelations;
        }
        internal List<string> loadOSMWays(string osmFileLocation, ref ITrackCancel TrackCancel, ref IGPMessages message, IGPValue targetGPValue, IFeatureClass osmPointFeatureClass, IFeatureClass osmLineFeatureClass, IFeatureClass osmPolygonFeatureClass, bool conserveMemory, bool fastLoad, int wayCapacity, ref Dictionary<string, simplePointRef> osmNodeDictionary, IFeatureWorkspace featureWorkspace, ISpatialReference downloadSpatialReference, OSMDomains availableDomains, bool checkForExisting)
        {
            if (osmLineFeatureClass == null)
            {
                throw new ArgumentNullException("osmLineFeatureClass");
            }

            if (osmPolygonFeatureClass == null)
            {
                throw new ArgumentNullException("osmPolygonFeatureClass");
            }

            XmlReader osmFileXmlReader = null;
            XmlSerializer waySerializer = null;
            List<string> missingWays = null;

            try
            {
                missingWays = new List<string>();

                int osmPointIDFieldIndex = osmPointFeatureClass.FindField("OSMID");
                int osmWayRefCountFieldIndex = osmPointFeatureClass.FindField("wayRefCount");

                int osmLineIDFieldIndex = osmLineFeatureClass.FindField("OSMID");
                Dictionary<string, int> osmLineDomainAttributeFieldIndices = new Dictionary<string, int>();
                Dictionary<string, int> osmLineDomainAttributeFieldLength = new Dictionary<string, int>();
                foreach (var domains in availableDomains.domain)
                {
                    int currentFieldIndex = osmLineFeatureClass.FindField(domains.name);

                    if (currentFieldIndex != -1)
                    {
                        osmLineDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex);
                        osmLineDomainAttributeFieldLength.Add(domains.name, osmLineFeatureClass.Fields.get_Field(currentFieldIndex).Length);
                    }
                }
                int tagCollectionPolylineFieldIndex = osmLineFeatureClass.FindField("osmTags");
                int osmUserPolylineFieldIndex = osmLineFeatureClass.FindField("osmuser");
                int osmUIDPolylineFieldIndex = osmLineFeatureClass.FindField("osmuid");
                int osmVisiblePolylineFieldIndex = osmLineFeatureClass.FindField("osmvisible");
                int osmVersionPolylineFieldIndex = osmLineFeatureClass.FindField("osmversion");
                int osmChangesetPolylineFieldIndex = osmLineFeatureClass.FindField("osmchangeset");
                int osmTimeStampPolylineFieldIndex = osmLineFeatureClass.FindField("osmtimestamp");
                int osmMemberOfPolylineFieldIndex = osmLineFeatureClass.FindField("osmMemberOf");
                int osmMembersPolylineFieldIndex = osmLineFeatureClass.FindField("osmMembers");
                int osmSupportingElementPolylineFieldIndex = osmLineFeatureClass.FindField("osmSupportingElement");

                int osmPolygonIDFieldIndex = osmPolygonFeatureClass.FindField("OSMID");
                Dictionary<string, int> osmPolygonDomainAttributeFieldIndices = new Dictionary<string, int>();
                Dictionary<string, int> osmPolygonDomainAttributeFieldLength = new Dictionary<string, int>();
                foreach (var domains in availableDomains.domain)
                {
                    int currentFieldIndex = osmPolygonFeatureClass.FindField(domains.name);

                    if (currentFieldIndex != -1)
                    {
                        osmPolygonDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex);
                        osmPolygonDomainAttributeFieldLength.Add(domains.name, osmPolygonFeatureClass.Fields.get_Field(currentFieldIndex).Length);
                    }
                }
                int tagCollectionPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmTags");
                int osmUserPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmuser");
                int osmUIDPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmuid");
                int osmVisiblePolygonFieldIndex = osmPolygonFeatureClass.FindField("osmvisible");
                int osmVersionPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmversion");
                int osmChangesetPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmchangeset");
                int osmTimeStampPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmtimestamp");
                int osmMemberOfPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmMemberOf");
                int osmMembersPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmMembers");
                int osmSupportingElementPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmSupportingElement");

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

                bool shouldProject = !((IClone)wgs84).IsEqual((IClone)downloadSpatialReference);

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

                if (stepProgressor != null)
                {
                    stepProgressor.MinRange = 0;
                    stepProgressor.MaxRange = wayCapacity;
                    stepProgressor.Position = 0;
                    stepProgressor.Message = _resourceManager.GetString("GPTools_OSMGPFileReader_loadingWays");
                    stepProgressor.StepValue = 1;
                    stepProgressor.Show();
                }

                bool lineIndexRebuildRequired = false;
                bool polygonIndexRebuildRequired = false;

                int wayCount = 0;
                object missingValue = System.Reflection.Missing.Value;

                // enterprise GDB indicator -- supporting load only mode
                IFeatureClassLoad lineFeatureLoad = null;
                IFeatureClassLoad polygonFeatureLoad = null;

                using (SchemaLockManager lineLock = new SchemaLockManager(osmLineFeatureClass as ITable), polygonLock = new SchemaLockManager(osmPolygonFeatureClass as ITable))
                {
                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        IFeatureCursor insertLineCursor = osmLineFeatureClass.Insert(true);
                        comReleaser.ManageLifetime(insertLineCursor);

                        IFeatureBuffer featureLineBuffer = osmLineFeatureClass.CreateFeatureBuffer();
                        comReleaser.ManageLifetime(featureLineBuffer);

                        IFeatureCursor insertPolygonCursor = osmPolygonFeatureClass.Insert(true);
                        comReleaser.ManageLifetime(insertPolygonCursor);

                        IFeatureBuffer featurePolygonBuffer = osmPolygonFeatureClass.CreateFeatureBuffer();
                        comReleaser.ManageLifetime(featurePolygonBuffer);

                        if (((IWorkspace)featureWorkspace).WorkspaceFactory.WorkspaceType == esriWorkspaceType.esriRemoteDatabaseWorkspace)
                        {
                            lineFeatureLoad = osmLineFeatureClass as IFeatureClassLoad;
                            polygonFeatureLoad = osmPolygonFeatureClass as IFeatureClassLoad;
                        }

                        if (lineFeatureLoad != null)
                        {
                            lineFeatureLoad.LoadOnlyMode = true;
                        }

                        if (polygonFeatureLoad != null)
                        {
                            polygonFeatureLoad.LoadOnlyMode = true;
                        }

                        ISpatialReference nativeLineSpatialReference = ((IGeoDataset)osmLineFeatureClass).SpatialReference;
                        ISpatialReference nativePolygonSpatialReference = ((IGeoDataset)osmPolygonFeatureClass).SpatialReference;

                        IQueryFilter osmIDQueryFilter = new QueryFilterClass();
                        string sqlPointOSMID = osmPointFeatureClass.SqlIdentifier("OSMID");
                        IFeatureCursor updatePointCursor = null;

                        osmFileXmlReader = System.Xml.XmlReader.Create(osmFileLocation);
                        waySerializer = new XmlSerializer(typeof(way));

                        // the point query filter for updates will not changes, so let's do that ahead of time
                        try
                        {
                            osmIDQueryFilter.SubFields = osmPointFeatureClass.ShapeFieldName + "," + osmPointFeatureClass.Fields.get_Field(osmPointIDFieldIndex).Name + "," + osmPointFeatureClass.Fields.get_Field(osmWayRefCountFieldIndex).Name;
                        }
                        catch
                        { }

                        osmFileXmlReader.MoveToContent();
                        while (osmFileXmlReader.Read())
                        {
                            if (osmFileXmlReader.IsStartElement())
                            {
                                if (osmFileXmlReader.Name == "way")
                                {
                                    string currentwayString = osmFileXmlReader.ReadOuterXml();

                                    // assuming the way to be a polyline is sort of a safe assumption
                                    // and won't cause any topology problem due to orientation and closeness
                                    bool wayIsLine = true;
                                    bool wayIsComplete = true;

                                    way currentWay = null;

                                    try
                                    {
                                        using (StringReader wayReader = new System.IO.StringReader(currentwayString))
                                        {
                                            currentWay = waySerializer.Deserialize(wayReader) as way;
                                        }

                                        // if the deserialization fails then go ahead and read the next xml element
                                        if (currentWay == null)
                                        {
                                            continue;
                                        }

                                        // and we are expecting at least some nodes on the way itself
                                        if (currentWay.nd == null)
                                        {
                                            continue;
                                        }

                                        featureLineBuffer = osmLineFeatureClass.CreateFeatureBuffer();
                                        featurePolygonBuffer = osmPolygonFeatureClass.CreateFeatureBuffer();

                                        IPointCollection wayPointCollection = null;
                                        wayIsLine = IsThisWayALine(currentWay);

                                        if (wayIsLine)
                                        {

                                            // check if a feature with the same OSMID already exists, because the can only be one
                                            if (checkForExisting == true)
                                            {
                                                if (CheckIfExists(osmLineFeatureClass as ITable, currentWay.id))
                                                {
                                                    continue;
                                                }
                                            }

                                            IPolyline wayPolyline = new PolylineClass();
                                            comReleaser.ManageLifetime(wayPointCollection);

                                            wayPolyline.SpatialReference = downloadSpatialReference;

                                            IPointIDAware polylineIDAware = wayPolyline as IPointIDAware;
                                            polylineIDAware.PointIDAware = true;

                                            wayPointCollection = wayPolyline as IPointCollection;

                                            # region generate line geometry
                                            if (conserveMemory == false)
                                            {
                                                for (int ndIndex = 0; ndIndex < currentWay.nd.Length; ndIndex++)
                                                {
                                                    string ndID = currentWay.nd[ndIndex].@ref;
                                                    if (osmNodeDictionary.ContainsKey(ndID))
                                                    {
                                                        IPoint newPoint = new PointClass();
                                                        newPoint.X = osmNodeDictionary[ndID].Longitude;
                                                        newPoint.Y = osmNodeDictionary[ndID].Latitude;

                                                        newPoint.SpatialReference = wgs84;

                                                        if (shouldProject)
                                                        {
                                                            newPoint.Project(((IGeoDataset)osmLineFeatureClass).SpatialReference);
                                                        }

                                                        IPointIDAware idAware = newPoint as IPointIDAware;
                                                        idAware.PointIDAware = true;

                                                        newPoint.ID = osmNodeDictionary[ndID].pointObjectID;

                                                        wayPointCollection.AddPoint(newPoint, ref missingValue, ref missingValue);

                                                        osmNodeDictionary[ndID].RefCounter = osmNodeDictionary[ndID].RefCounter + 1;
                                                    }
                                                    else
                                                    {
                                                        message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_undeterminedline_node"), currentWay.id, ndID));
                                                        // set the flag that the way is complete due to a missing node
                                                        wayIsComplete = false;
                                                        break;
                                                    }
                                                }

                                            }
                                            else
                                            {
                                                for (int pointIndex = 0; pointIndex < currentWay.nd.Length; pointIndex++)
                                                {
                                                    wayPointCollection.AddPoint(new PointClass());
                                                }

                                                List<string> idRequests = SplitOSMIDRequests(currentWay, 2);

                                                // build a list of node ids we can use to determine the point index in the line geometry
                                                // as well as a dictionary to determine the position in the list in case of duplicates nodes
                                                Dictionary<string, int> nodePositionDictionary = new Dictionary<string, int>(currentWay.nd.Length);
                                                List<string> nodeIDs = new List<string>(currentWay.nd.Length);

                                                foreach (nd wayNode in currentWay.nd)
                                                {
                                                    nodeIDs.Add(wayNode.@ref);

                                                    if (nodePositionDictionary.ContainsKey(wayNode.@ref) == false)
                                                    {
                                                        nodePositionDictionary.Add(wayNode.@ref, 0);
                                                    }
                                                }

                                                try
                                                {
                                                    osmIDQueryFilter.SubFields = osmPointFeatureClass.ShapeFieldName + "," + osmPointFeatureClass.Fields.get_Field(osmPointIDFieldIndex).Name + "," + osmPointFeatureClass.Fields.get_Field(osmWayRefCountFieldIndex).Name;
                                                }
                                                catch
                                                { }

                                                foreach (string request in idRequests)
                                                {
                                                    string idCompareString = request;
                                                    osmIDQueryFilter.WhereClause = sqlPointOSMID + " IN " + request;
                                                    using (ComReleaser innerComReleaser = new ComReleaser())
                                                    {
                                                        updatePointCursor = osmPointFeatureClass.Update(osmIDQueryFilter, true);
                                                        innerComReleaser.ManageLifetime(updatePointCursor);

                                                        IFeature nodeFeature = updatePointCursor.NextFeature();

                                                        while (nodeFeature != null)
                                                        {
                                                            // determine the index of the point in with respect to the node position
                                                            string nodeOSMIDString = Convert.ToString(nodeFeature.get_Value(osmPointIDFieldIndex));

                                                            // remove the ID from the request string
                                                            idCompareString = idCompareString.Replace(nodeOSMIDString, String.Empty);

                                                            int nodePositionIndex = -1;

                                                            while ((nodePositionIndex = nodeIDs.IndexOf(nodeOSMIDString, nodePositionDictionary[nodeOSMIDString])) != -1)
                                                            {
                                                                //// update the new position start search index
                                                                nodePositionDictionary[nodeOSMIDString] = nodePositionIndex + 1;

                                                                wayPointCollection.UpdatePoint(nodePositionIndex, (IPoint)nodeFeature.Shape);

                                                                // increase the reference counter
                                                                if (osmWayRefCountFieldIndex != -1)
                                                                {
                                                                    nodeFeature.set_Value(osmWayRefCountFieldIndex, ((int)nodeFeature.get_Value(osmWayRefCountFieldIndex)) + 1);

                                                                    updatePointCursor.UpdateFeature(nodeFeature);
                                                                }
                                                            }

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

                                                            nodeFeature = updatePointCursor.NextFeature();
                                                        }

                                                        idCompareString = CleanReportedNodes(idCompareString);

                                                        // after removing the commas we should be left with only paranthesis left, meaning a string of length 2
                                                        // if we have more then we have found a missing node, resulting in an incomplete way geometry
                                                        if (idCompareString.Length > 2)
                                                        {
                                                            message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_undeterminedline_node"), currentWay.id, idCompareString));
                                                            wayIsComplete = false;
                                                        }
                                                    }
                                                }
                                            }
                                            #endregion

                                            if (wayIsComplete == false)
                                            {
                                                // if the way geometry is incomplete due to a missing node let's continue to the next way element
                                                missingWays.Add(currentWay.id);
                                                continue;
                                            }

                                            featureLineBuffer.Shape = wayPolyline;
                                            featureLineBuffer.set_Value(osmLineIDFieldIndex, currentWay.id);
                                        }
                                        else
                                        {
                                            // check if a feature with the same OSMID already exists, because the can only be one
                                            if (checkForExisting == true)
                                            {
                                                if (CheckIfExists(osmPolygonFeatureClass as ITable, currentWay.id))
                                                {
                                                    continue;
                                                }
                                            }

                                            IPolygon wayPolygon = new PolygonClass();
                                            comReleaser.ManageLifetime(wayPointCollection);

                                            wayPolygon.SpatialReference = downloadSpatialReference;

                                            IPointIDAware polygonIDAware = wayPolygon as IPointIDAware;
                                            polygonIDAware.PointIDAware = true;

                                            wayPointCollection = wayPolygon as IPointCollection;

                                            #region generate polygon geometry
                                            if (conserveMemory == false)
                                            {
                                                for (int ndIndex = 0; ndIndex < currentWay.nd.Length; ndIndex++)
                                                {
                                                    string ndID = currentWay.nd[ndIndex].@ref;
                                                    if (osmNodeDictionary.ContainsKey(ndID))
                                                    {
                                                        IPoint newPoint = new PointClass();
                                                        newPoint.X = osmNodeDictionary[ndID].Longitude;
                                                        newPoint.Y = osmNodeDictionary[ndID].Latitude;
                                                        newPoint.SpatialReference = wgs84;

                                                        if (shouldProject)
                                                        {
                                                            newPoint.Project(nativePolygonSpatialReference);
                                                        }

                                                        IPointIDAware idAware = newPoint as IPointIDAware;
                                                        idAware.PointIDAware = true;

                                                        newPoint.ID = osmNodeDictionary[ndID].pointObjectID;

                                                        wayPointCollection.AddPoint(newPoint, ref missingValue, ref missingValue);
                                                    }
                                                    else
                                                    {
                                                        message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_undeterminedpolygon_node"), currentWay.id, ndID));
                                                        wayIsComplete = false;
                                                        break;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                for (int pointIndex = 0; pointIndex < currentWay.nd.Length; pointIndex++)
                                                {
                                                    wayPointCollection.AddPoint(new PointClass());
                                                }

                                                List<string> idRequests = SplitOSMIDRequests(currentWay, 2);

                                                // build a list of node ids we can use to determine the point index in the line geometry
                                                // as well as a dictionary to determine the position in the list in case of duplicates nodes
                                                Dictionary<string, int> nodePositionDictionary = new Dictionary<string, int>(currentWay.nd.Length);
                                                List<string> nodeIDs = new List<string>(currentWay.nd.Length);

                                                foreach (nd wayNode in currentWay.nd)
                                                {
                                                    nodeIDs.Add(wayNode.@ref);

                                                    if (nodePositionDictionary.ContainsKey(wayNode.@ref) == false)
                                                    {
                                                        nodePositionDictionary.Add(wayNode.@ref, 0);
                                                    }
                                                }

                                                try
                                                {
                                                    osmIDQueryFilter.SubFields = osmPointFeatureClass.ShapeFieldName + "," + osmPointFeatureClass.Fields.get_Field(osmPointIDFieldIndex).Name + "," + osmPointFeatureClass.Fields.get_Field(osmWayRefCountFieldIndex).Name;
                                                }
                                                catch
                                                { }

                                                foreach (string osmIDRequest in idRequests)
                                                {
                                                    string idCompareString = osmIDRequest;

                                                    using (ComReleaser innercomReleaser = new ComReleaser())
                                                    {
                                                        osmIDQueryFilter.WhereClause = sqlPointOSMID + " IN " + osmIDRequest;
                                                        updatePointCursor = osmPointFeatureClass.Update(osmIDQueryFilter, false);
                                                        innercomReleaser.ManageLifetime(updatePointCursor);

                                                        IFeature nodeFeature = updatePointCursor.NextFeature();

                                                        while (nodeFeature != null)
                                                        {
                                                            // determine the index of the point in with respect to the node position
                                                            string nodeOSMIDString = Convert.ToString(nodeFeature.get_Value(osmPointIDFieldIndex));

                                                            idCompareString = idCompareString.Replace(nodeOSMIDString, String.Empty);

                                                            int nodePositionIndex = nodeIDs.IndexOf(nodeOSMIDString, nodePositionDictionary[nodeOSMIDString]);

                                                            // update the new position start search index
                                                            nodePositionDictionary[nodeOSMIDString] = nodePositionIndex + 1;

                                                            wayPointCollection.UpdatePoint(nodePositionIndex, (IPoint)nodeFeature.Shape);

                                                            // increase the reference counter
                                                            if (osmWayRefCountFieldIndex != -1)
                                                            {
                                                                nodeFeature.set_Value(osmWayRefCountFieldIndex, ((int)nodeFeature.get_Value(osmWayRefCountFieldIndex)) + 1);

                                                                updatePointCursor.UpdateFeature(nodeFeature);
                                                            }

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

                                                            nodeFeature = updatePointCursor.NextFeature();
                                                        }

                                                        idCompareString = CleanReportedNodes(idCompareString);

                                                        if (idCompareString.Length > 2)
                                                        {
                                                            message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_undeterminedpolygon_node"), currentWay.id, idCompareString));
                                                            wayIsComplete = false;
                                                        }
                                                    }
                                                }
                                            }
                                            #endregion

                                            if (wayIsComplete == false)
                                            {
                                                continue;
                                            }

                                            // remove the last point as OSM considers them to be coincident
                                            wayPointCollection.RemovePoints(wayPointCollection.PointCount - 1, 1);
                                            ((IPolygon)wayPointCollection).Close();

                                            featurePolygonBuffer.Shape = (IPolygon)wayPointCollection;
                                            featurePolygonBuffer.set_Value(osmPolygonIDFieldIndex, currentWay.id);
                                        }

                                        if (wayIsLine)
                                        {
                                            insertTags(osmLineDomainAttributeFieldIndices, osmLineDomainAttributeFieldLength, tagCollectionPolylineFieldIndex, featureLineBuffer, currentWay.tag);
                                        }
                                        else
                                        {
                                            insertTags(osmPolygonDomainAttributeFieldIndices, osmPolygonDomainAttributeFieldLength, tagCollectionPolygonFieldIndex, featurePolygonBuffer, currentWay.tag);
                                        }

                                        // store the administrative attributes
                                        // user, uid, version, changeset, timestamp, visible
                                        if (fastLoad == false)
                                        {
                                            if (!String.IsNullOrEmpty(currentWay.user))
                                            {
                                                if (wayIsLine)
                                                {
                                                    if (osmUserPolylineFieldIndex != -1)
                                                    {
                                                        featureLineBuffer.set_Value(osmUserPolylineFieldIndex, currentWay.user);
                                                    }
                                                }
                                                else
                                                {
                                                    if (osmUserPolygonFieldIndex != -1)
                                                    {
                                                        featurePolygonBuffer.set_Value(osmUserPolygonFieldIndex, currentWay.user);
                                                    }
                                                }
                                            }

                                            if (!String.IsNullOrEmpty(currentWay.uid))
                                            {
                                                if (wayIsLine)
                                                {
                                                    if (osmUIDPolylineFieldIndex != -1)
                                                    {
                                                        featureLineBuffer.set_Value(osmUIDPolylineFieldIndex, Convert.ToInt32(currentWay.uid));
                                                    }
                                                }
                                                else
                                                {
                                                    if (osmUIDPolygonFieldIndex != -1)
                                                    {
                                                        featurePolygonBuffer.set_Value(osmUIDPolygonFieldIndex, Convert.ToInt32(currentWay.uid));
                                                    }
                                                }
                                            }

                                            if (wayIsLine)
                                            {
                                                if (osmVisiblePolylineFieldIndex != -1)
                                                {
                                                    featureLineBuffer.set_Value(osmVisiblePolylineFieldIndex, currentWay.visible.ToString());
                                                }
                                            }
                                            else
                                            {
                                                if (osmVisiblePolygonFieldIndex != -1)
                                                {
                                                    featurePolygonBuffer.set_Value(osmVisiblePolygonFieldIndex, currentWay.visible.ToString());
                                                }
                                            }

                                            if (!String.IsNullOrEmpty(currentWay.version))
                                            {
                                                if (wayIsLine)
                                                {
                                                    if (osmVersionPolylineFieldIndex != -1)
                                                    {
                                                        featureLineBuffer.set_Value(osmVersionPolylineFieldIndex, Convert.ToInt32(currentWay.version));
                                                    }
                                                }
                                                else
                                                {
                                                    if (osmVersionPolygonFieldIndex != -1)
                                                    {
                                                        featurePolygonBuffer.set_Value(osmVersionPolygonFieldIndex, Convert.ToInt32(currentWay.version));
                                                    }
                                                }
                                            }

                                            if (!String.IsNullOrEmpty(currentWay.changeset))
                                            {
                                                if (wayIsLine)
                                                {
                                                    if (osmChangesetPolylineFieldIndex != -1)
                                                    {
                                                        featureLineBuffer.set_Value(osmChangesetPolylineFieldIndex, Convert.ToInt32(currentWay.changeset));
                                                    }
                                                }
                                                else
                                                {
                                                    if (osmChangesetPolygonFieldIndex != -1)
                                                    {
                                                        featurePolygonBuffer.set_Value(osmChangesetPolygonFieldIndex, Convert.ToInt32(currentWay.changeset));
                                                    }
                                                }
                                            }

                                            if (!String.IsNullOrEmpty(currentWay.timestamp))
                                            {
                                                try
                                                {
                                                    if (wayIsLine)
                                                    {
                                                        if (osmTimeStampPolylineFieldIndex != -1)
                                                        {
                                                            featureLineBuffer.set_Value(osmTimeStampPolylineFieldIndex, Convert.ToDateTime(currentWay.timestamp));
                                                        }
                                                    }
                                                    else
                                                    {
                                                        if (osmTimeStampPolygonFieldIndex != -1)
                                                        {
                                                            featurePolygonBuffer.set_Value(osmTimeStampPolygonFieldIndex, Convert.ToDateTime(currentWay.timestamp));
                                                        }
                                                    }
                                                }
                                                catch (Exception ex)
                                                {
                                                    message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_invalidTimeFormat"), ex.Message));
                                                }
                                            }

                                            if (wayIsLine)
                                            {
                                                if (osmSupportingElementPolylineFieldIndex > -1)
                                                {
                                                    if (currentWay.tag == null)
                                                    {
                                                        featureLineBuffer.set_Value(osmSupportingElementPolylineFieldIndex, "yes");
                                                    }
                                                    else
                                                    {
                                                        featureLineBuffer.set_Value(osmSupportingElementPolylineFieldIndex, "no");
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                if (osmSupportingElementPolygonFieldIndex > -1)
                                                {
                                                    if (currentWay.tag == null)
                                                    {
                                                        featurePolygonBuffer.set_Value(osmSupportingElementPolygonFieldIndex, "yes");
                                                    }
                                                    else
                                                    {
                                                        featurePolygonBuffer.set_Value(osmSupportingElementPolygonFieldIndex, "no");
                                                    }
                                                }
                                            }
                                        } // fast load

                                        try
                                        {
                                            if (wayIsLine)
                                            {
                                                insertLineCursor.InsertFeature(featureLineBuffer);
                                                lineIndexRebuildRequired = true;
                                            }
                                            else
                                            {
                                                insertPolygonCursor.InsertFeature(featurePolygonBuffer);
                                                polygonIndexRebuildRequired = true;
                                            }

                                            wayCount = wayCount + 1;

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

                                            if ((wayCount % 50000) == 0)
                                            {
                                                message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_waysloaded"), wayCount));
                                            }

                                        }
                                        catch (Exception ex)
                                        {
                                            message.AddWarning(ex.Message);
                                            message.AddWarning(currentwayString);
                                        }

                                    }
                                    catch (Exception ex)
                                    {
                                        System.Diagnostics.Debug.WriteLine(ex.Message);
                                        System.Diagnostics.Debug.WriteLine(ex.StackTrace);
                                    }
                                    finally
                                    {
                                        if (featureLineBuffer != null)
                                        {
                                            Marshal.ReleaseComObject(featureLineBuffer);

                                            if (featureLineBuffer != null)
                                                featureLineBuffer = null;
                                        }

                                        if (featurePolygonBuffer != null)
                                        {
                                            Marshal.ReleaseComObject(featurePolygonBuffer);

                                            if (featurePolygonBuffer != null)
                                                featurePolygonBuffer = null;
                                        }

                                        currentWay = null;
                                    }

                                    if (TrackCancel.Continue() == false)
                                    {
                                        insertPolygonCursor.Flush();
                                        if (polygonFeatureLoad != null)
                                        {
                                            polygonFeatureLoad.LoadOnlyMode = false;
                                        }

                                        insertLineCursor.Flush();
                                        if (lineFeatureLoad != null)
                                        {
                                            lineFeatureLoad.LoadOnlyMode = false;
                                        }

                                        return missingWays;
                                    }
                                }
                            }
                        }

                        osmFileXmlReader.Close();

                        if (stepProgressor != null)
                        {
                            stepProgressor.Hide();
                        }

                        message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_waysloaded"), wayCount));

                        insertPolygonCursor.Flush();
                        if (polygonFeatureLoad != null)
                        {
                            polygonFeatureLoad.LoadOnlyMode = false;
                        }

                        insertLineCursor.Flush();
                        if (lineFeatureLoad != null)
                        {
                            lineFeatureLoad.LoadOnlyMode = false;
                        }
                    }
                }

                IGeoProcessor2 geoProcessor = new GeoProcessorClass();
                IGPUtilities3 gpUtilities3 = new GPUtilitiesClass();
                bool storedOriginal = geoProcessor.AddOutputsToMap;
                IVariantArray parameterArrary = null;
                IGeoProcessorResult2 gpResults2 = null;

                try
                {
                    geoProcessor.AddOutputsToMap = false;

                    if (lineIndexRebuildRequired)
                    {
                        IIndexes featureClassIndexes = osmLineFeatureClass.Indexes;
                        int indexPosition = -1;
                        featureClassIndexes.FindIndex("osmID_IDX", out indexPosition);

                        string fcLocation = GetLocationString(targetGPValue, osmLineFeatureClass);

                        if (indexPosition == -1)
                        {
                            message.AddMessage(_resourceManager.GetString("GPTools_buildinglineidx"));

                            // Addd index for osmid column
                            parameterArrary = CreateAddIndexParameterArray(fcLocation, "OSMID", "osmID_IDX", "UNIQUE", "");
                            gpResults2 = geoProcessor.Execute("AddIndex_management", parameterArrary, TrackCancel) as IGeoProcessorResult2;
                        }

                        if (wayCount > 100)
                        {
                            // in this case we are dealing with a file geodatabase
                            if (lineFeatureLoad == null)
                            {
                                UpdateSpatialGridIndex(TrackCancel, message, geoProcessor, fcLocation);
                            }
                        }
                    }

                    if (polygonIndexRebuildRequired)
                    {
                        IIndexes featureClassIndexes = osmPolygonFeatureClass.Indexes;
                        int indexPosition = -1;
                        featureClassIndexes.FindIndex("osmID_IDX", out indexPosition);

                        string fcLocation = GetLocationString(targetGPValue, osmPolygonFeatureClass);

                        if (indexPosition == -1)
                        {
                            message.AddMessage(_resourceManager.GetString("GPTools_buildingpolygonidx"));

                            IGPValue polygonFeatureClassGPValue = gpUtilities3.MakeGPValueFromObject(osmPolygonFeatureClass);

                            if (polygonFeatureClassGPValue != null)
                            {
                                // Addd index for osmid column
                                parameterArrary = CreateAddIndexParameterArray(fcLocation, "OSMID", "osmID_IDX", "UNIQUE", "");
                                gpResults2 = geoProcessor.Execute("AddIndex_management", parameterArrary, TrackCancel) as IGeoProcessorResult2;
                            }
                        }

                        if (wayCount > 100)
                        {
                            if (polygonFeatureLoad == null)
                            {
                                UpdateSpatialGridIndex(TrackCancel, message, geoProcessor, fcLocation);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    message.AddWarning(ex.Message);
                }
                finally
                {
                    geoProcessor.AddOutputsToMap = storedOriginal;

                    Marshal.FinalReleaseComObject(gpUtilities3);
                    Marshal.FinalReleaseComObject(geoProcessor);
                }
            }
            catch (Exception ex)
            {
                message.AddWarning(ex.Message);
            }
            finally
            {
                if (waySerializer != null)
                    waySerializer = null;

                if (osmFileXmlReader != null)
                    osmFileXmlReader = null;

                System.GC.Collect();
                System.GC.WaitForPendingFinalizers();
            }

            return missingWays;
        }
        internal void loadOSMNodes(string osmFileLocation, ref ITrackCancel TrackCancel, ref IGPMessages message,IGPValue targetGPValue,  IFeatureClass osmPointFeatureClass, bool conserveMemory, bool fastLoad, int nodeCapacity, ref Dictionary<string, simplePointRef> osmNodeDictionary, IFeatureWorkspace featureWorkspace, ISpatialReference downloadSpatialReference, OSMDomains availableDomains, bool checkForExisting)
        {
            XmlReader osmFileXmlReader = null;
            XmlSerializer nodeSerializer = null;

            try
            {
                osmFileXmlReader = System.Xml.XmlReader.Create(osmFileLocation);
                nodeSerializer = new XmlSerializer(typeof(node));

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

                bool shouldProject = !((IClone)wgs84).IsEqual((IClone)downloadSpatialReference);

                int osmPointIDFieldIndex = osmPointFeatureClass.FindField("OSMID");
                Dictionary<string, int> osmPointDomainAttributeFieldIndices = new Dictionary<string, int>();
                Dictionary<string, int> osmPointDomainAttributeFieldLength = new Dictionary<string, int>();

                foreach (var domains in availableDomains.domain)
                {
                    int currentFieldIndex = osmPointFeatureClass.FindField(domains.name);

                    if (currentFieldIndex != -1)
                    {
                        osmPointDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex);
                        osmPointDomainAttributeFieldLength.Add(domains.name, osmPointFeatureClass.Fields.get_Field(currentFieldIndex).Length);
                    }
                }

                int tagCollectionPointFieldIndex = osmPointFeatureClass.FindField("osmTags");
                int osmUserPointFieldIndex = osmPointFeatureClass.FindField("osmuser");
                int osmUIDPointFieldIndex = osmPointFeatureClass.FindField("osmuid");
                int osmVisiblePointFieldIndex = osmPointFeatureClass.FindField("osmvisible");
                int osmVersionPointFieldIndex = osmPointFeatureClass.FindField("osmversion");
                int osmChangesetPointFieldIndex = osmPointFeatureClass.FindField("osmchangeset");
                int osmTimeStampPointFieldIndex = osmPointFeatureClass.FindField("osmtimestamp");
                int osmMemberOfPointFieldIndex = osmPointFeatureClass.FindField("osmMemberOf");
                int osmSupportingElementPointFieldIndex = osmPointFeatureClass.FindField("osmSupportingElement");
                int osmWayRefCountFieldIndex = osmPointFeatureClass.FindField("wayRefCount");

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

                if (stepProgressor != null)
                {
                    stepProgressor.MinRange = 0;
                    stepProgressor.MaxRange = nodeCapacity;
                    stepProgressor.StepValue = (1);
                    stepProgressor.Message = _resourceManager.GetString("GPTools_OSMGPFileReader_loadingNodes");
                    stepProgressor.Position = 0;
                    stepProgressor.Show();
                }

                // flag to determine if a computation of indices is required
                bool indexBuildRequired = false;
                if (nodeCapacity > 0)
                    indexBuildRequired = true;

                int pointCount = 0;

                // let's insert all the points first
                if (osmPointFeatureClass != null)
                {
                    IFeatureBuffer pointFeature = null;
                    IFeatureClassLoad pointFeatureLoad = null;

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        using (SchemaLockManager schemaLockManager = new SchemaLockManager(osmPointFeatureClass as ITable))
                        {

                            if (((IWorkspace)featureWorkspace).WorkspaceFactory.WorkspaceType == esriWorkspaceType.esriRemoteDatabaseWorkspace)
                            {
                                pointFeatureLoad = osmPointFeatureClass as IFeatureClassLoad;
                            }

                            IFeatureCursor pointInsertCursor = osmPointFeatureClass.Insert(true);
                            comReleaser.ManageLifetime(pointInsertCursor);

                            pointFeature = osmPointFeatureClass.CreateFeatureBuffer();
                            comReleaser.ManageLifetime(pointFeature);

                            if (pointFeatureLoad != null)
                            {
                                pointFeatureLoad.LoadOnlyMode = true;
                            }

                            osmFileXmlReader.MoveToContent();

                            while (osmFileXmlReader.Read())
                            {
                                if (osmFileXmlReader.IsStartElement())
                                {
                                    if (osmFileXmlReader.Name == "node")
                                    {
                                        string currentNodeString = osmFileXmlReader.ReadOuterXml();
                                        // turn the xml node representation into a node class representation
                                        ESRI.ArcGIS.OSM.OSMClassExtension.node currentNode = null;
                                        using (StringReader nodeReader = new System.IO.StringReader(currentNodeString))
                                        {
                                            currentNode = nodeSerializer.Deserialize(nodeReader) as ESRI.ArcGIS.OSM.OSMClassExtension.node;
                                        }

                                        // check if a feature with the same OSMID already exists, because the can only be one
                                        if (checkForExisting == true)
                                        {
                                            if (CheckIfExists(osmPointFeatureClass as ITable, currentNode.id))
                                            {
                                                continue;
                                            }
                                        }

                                        try
                                        {
                                            //if (pointFeature == null)
                                            //{
                                            pointFeature = osmPointFeatureClass.CreateFeatureBuffer();
                                            comReleaser.ManageLifetime(pointFeature);
                                            //}

                                            IPoint pointGeometry = new PointClass();
                                            comReleaser.ManageLifetime(pointGeometry);

                                            pointGeometry.X = Convert.ToDouble(currentNode.lon, new CultureInfo("en-US"));
                                            pointGeometry.Y = Convert.ToDouble(currentNode.lat, new CultureInfo("en-US"));
                                            pointGeometry.SpatialReference = wgs84;

                                            if (shouldProject)
                                            {
                                                pointGeometry.Project(downloadSpatialReference);
                                            }

                                            pointFeature.Shape = pointGeometry;

                                            pointFeature.set_Value(osmPointIDFieldIndex, currentNode.id);

                                            string isSupportingNode = "";
                                            if (_osmUtility.DoesHaveKeys(currentNode))
                                            {
                                                // if case it has tags I assume that the node presents an entity of it own,
                                                // hence it is not a supporting node in the context of supporting a way or relation
                                                isSupportingNode = "no";

                                                if (conserveMemory == false)
                                                {
                                                    osmNodeDictionary[currentNode.id] = new simplePointRef(Convert.ToSingle(currentNode.lon, new CultureInfo("en-US")), Convert.ToSingle(currentNode.lat, new CultureInfo("en-US")), 0, 0);
                                                }
                                            }
                                            else
                                            {
                                                // node has no tags -- at this point I assume that the absence of tags indicates that it is a supporting node
                                                // for a way or a relation
                                                isSupportingNode = "yes";

                                                if (conserveMemory == false)
                                                {
                                                    osmNodeDictionary[currentNode.id] = new simplePointRef(Convert.ToSingle(currentNode.lon, new CultureInfo("en-US")), Convert.ToSingle(currentNode.lat, new CultureInfo("en-US")), 0, 0);
                                                }
                                            }

                                            insertTags(osmPointDomainAttributeFieldIndices, osmPointDomainAttributeFieldLength, tagCollectionPointFieldIndex, pointFeature, currentNode.tag);

                                            if (fastLoad == false)
                                            {
                                                if (osmSupportingElementPointFieldIndex > -1)
                                                {
                                                    pointFeature.set_Value(osmSupportingElementPointFieldIndex, isSupportingNode);
                                                }

                                                if (osmWayRefCountFieldIndex > -1)
                                                {
                                                    pointFeature.set_Value(osmWayRefCountFieldIndex, 0);
                                                }

                                                // store the administrative attributes
                                                // user, uid, version, changeset, timestamp, visible
                                                if (osmUserPointFieldIndex > -1)
                                                {
                                                    if (!String.IsNullOrEmpty(currentNode.user))
                                                    {
                                                        pointFeature.set_Value(osmUserPointFieldIndex, currentNode.user);
                                                    }
                                                }

                                                if (osmUIDPointFieldIndex > -1)
                                                {
                                                    if (!String.IsNullOrEmpty(currentNode.uid))
                                                    {
                                                        pointFeature.set_Value(osmUIDPointFieldIndex, Convert.ToInt32(currentNode.uid));
                                                    }
                                                }

                                                if (osmVisiblePointFieldIndex > -1)
                                                {
                                                    pointFeature.set_Value(osmVisiblePointFieldIndex, currentNode.visible.ToString());
                                                }

                                                if (osmVersionPointFieldIndex > -1)
                                                {
                                                    if (!String.IsNullOrEmpty(currentNode.version))
                                                    {
                                                        pointFeature.set_Value(osmVersionPointFieldIndex, Convert.ToInt32(currentNode.version));
                                                    }
                                                }

                                                if (osmChangesetPointFieldIndex > -1)
                                                {
                                                    if (!String.IsNullOrEmpty(currentNode.changeset))
                                                    {
                                                        pointFeature.set_Value(osmChangesetPointFieldIndex, Convert.ToInt32(currentNode.changeset));
                                                    }
                                                }

                                                if (osmTimeStampPointFieldIndex > -1)
                                                {
                                                    if (!String.IsNullOrEmpty(currentNode.timestamp))
                                                    {
                                                        try
                                                        {
                                                            pointFeature.set_Value(osmTimeStampPointFieldIndex, Convert.ToDateTime(currentNode.timestamp));
                                                        }
                                                        catch (Exception ex)
                                                        {
                                                            message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_invalidTimeFormat"), ex.Message));
                                                        }
                                                    }
                                                }
                                            }
                                            try
                                            {
                                                pointInsertCursor.InsertFeature(pointFeature);
                                                pointCount = pointCount + 1;

                                                if (stepProgressor != null)
                                                {
                                                    stepProgressor.Position = pointCount;
                                                }
                                            }
                                            catch (Exception ex)
                                            {
                                                System.Diagnostics.Debug.WriteLine(ex.Message);
                                                message.AddWarning(ex.Message);
                                            }

                                            if (TrackCancel.Continue() == false)
                                            {
                                                return;
                                            }

                                            if ((pointCount % 50000) == 0)
                                            {
                                                message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_pointsloaded"), pointCount));
                                                pointInsertCursor.Flush();
                                                System.GC.Collect();
                                            }

                                            if (pointGeometry != null)
                                                Marshal.ReleaseComObject(pointGeometry);
                                        }
                                        catch (Exception ex)
                                        {
                                            System.Diagnostics.Debug.WriteLine(ex.Message);
                                            message.AddWarning(ex.Message);
                                        }
                                        finally
                                        {
                                            if (pointFeature != null)
                                            {
                                                Marshal.ReleaseComObject(pointFeature);

                                                if (pointFeature != null)
                                                    pointFeature = null;

                                            }
                                        }

                                        currentNode = null;
                                    }
                                }
                            }

                            if (stepProgressor != null)
                            {
                                stepProgressor.Hide();
                            }

                            pointInsertCursor.Flush();
                            osmFileXmlReader.Close();

                            message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_pointsloaded"), pointCount));
                            message.AddMessage(_resourceManager.GetString("GPTools_buildingpointidx"));

                            if (pointFeatureLoad != null)
                            {
                                pointFeatureLoad.LoadOnlyMode = false;
                            }
                        }
                    }

                    if (TrackCancel.Continue() == false)
                    {
                        return;
                    }

                    using (ComReleaser comReleaser = new ComReleaser())
                    {
                        IFeatureCursor updatePoints = osmPointFeatureClass.Update(null, false);
                        comReleaser.ManageLifetime(updatePoints);

                        IFeature feature2Update = updatePoints.NextFeature();

                        while (feature2Update != null)
                        {
                            IPoint pointGeometry = feature2Update.Shape as IPoint;
                            pointGeometry.ID = feature2Update.OID;
                            feature2Update.Shape = pointGeometry;

                            if (conserveMemory == false)
                            {
                                string osmid = Convert.ToString(feature2Update.get_Value(osmPointIDFieldIndex));
                                if (osmNodeDictionary.ContainsKey(osmid))
                                    osmNodeDictionary[osmid].pointObjectID = feature2Update.OID;
                            }

                            updatePoints.UpdateFeature(feature2Update);

                            if (TrackCancel.Continue() == false)
                            {
                                return;
                            }

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

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

                            feature2Update = updatePoints.NextFeature();
                        }
                    }

                    if (indexBuildRequired)
                    {

                        IGeoProcessor2 geoProcessor = new GeoProcessorClass();
                        bool storedOriginal = geoProcessor.AddOutputsToMap;

                        try
                        {
                            IGPUtilities3 gpUtilities3 = new GPUtilitiesClass();

                            IGPValue pointFeatureClass = gpUtilities3.MakeGPValueFromObject(osmPointFeatureClass);

                            string fcLocation = GetLocationString(targetGPValue, osmPointFeatureClass);

                            IIndexes featureClassIndexes = osmPointFeatureClass.Indexes;
                            int indexPosition = -1;
                            featureClassIndexes.FindIndex("osmID_IDX", out indexPosition);

                            if (indexPosition == -1)
                            {
                                {
                                    geoProcessor.AddOutputsToMap = false;

                                    IVariantArray parameterArrary = CreateAddIndexParameterArray(fcLocation, "OSMID", "osmID_IDX", "UNIQUE", "");
                                    IGeoProcessorResult2 gpResults2 = geoProcessor.Execute("AddIndex_management", parameterArrary, TrackCancel) as IGeoProcessorResult2;
                                }
                            }
                            if (pointCount > 500)
                            {
                                if (pointFeatureLoad == null)
                                {
                                    UpdateSpatialGridIndex(TrackCancel, message, geoProcessor, fcLocation);
                                }
                            }
                        }
                        catch (COMException comEx)
                        {
                            message.AddWarning(comEx.Message);
                        }
                        catch (Exception ex)
                        {
                            message.AddWarning(ex.Message);
                        }
                        finally
                        {
                            geoProcessor.AddOutputsToMap = storedOriginal;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                message.AddError(120100, String.Format(_resourceManager.GetString("GPTools_Utility_NodeLoadError"), ex.Message));
            }
            finally
            {
                if (osmFileXmlReader != null)
                    osmFileXmlReader = null;

                if (nodeSerializer != null)
                    nodeSerializer = null;
            }
        }