/// <summary>
        /// Exports element as Wall.
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="element">The element.</param>
        /// <param name="connectedWalls">Information about walls joined to this wall.</param>
        /// <param name="geometryElement">The geometry element.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        public static void ExportWall(ExporterIFC exporterIFC, Element element, IList<IList<IFCConnectedWallData>> connectedWalls, GeometryElement geometryElement, 
           ProductWrapper productWrapper)
        {
            IList<IFCAnyHandle> createdWalls = new List<IFCAnyHandle>();

            // We will not split walls and columns if the assemblyId is set, as we would like to keep the original wall
            // associated with the assembly, on the level of the assembly.
            bool splitWall = ExporterCacheManager.ExportOptionsCache.WallAndColumnSplitting && (element.AssemblyInstanceId == ElementId.InvalidElementId);
            if (splitWall)
            {
                Wall wallElement = element as Wall;
                IList<ElementId> levels = new List<ElementId>();
                IList<IFCRange> ranges = new List<IFCRange>();
                if (wallElement != null && geometryElement != null)
                {
                    LevelUtil.CreateSplitLevelRangesForElement(exporterIFC, IFCExportType.IfcWall, element, out levels, out ranges);
                }

                int numPartsToExport = ranges.Count;
                if (numPartsToExport == 0)
                {
                    IFCAnyHandle wallElemHnd = ExportWallBase(exporterIFC, element, connectedWalls, geometryElement, productWrapper, ElementId.InvalidElementId, null);
                    if (!IFCAnyHandleUtil.IsNullOrHasNoValue(wallElemHnd))
                        createdWalls.Add(wallElemHnd);
                }
                else
                {
                    using (ExporterStateManager.RangeIndexSetter rangeSetter = new ExporterStateManager.RangeIndexSetter())
                    {
                        for (int ii = 0; ii < numPartsToExport; ii++)
                        {
                            rangeSetter.IncreaseRangeIndex();
                            IFCAnyHandle wallElemHnd = ExportWallBase(exporterIFC, element, connectedWalls, geometryElement, productWrapper, levels[ii], ranges[ii]);
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(wallElemHnd))
                                createdWalls.Add(wallElemHnd);
                        }
                    }
                }

                if (ExporterCacheManager.DummyHostCache.HasRegistered(element.Id))
                {
                    using (ExporterStateManager.RangeIndexSetter rangeSetter = new ExporterStateManager.RangeIndexSetter())
                    {
                        List<KeyValuePair<ElementId, IFCRange>> levelRangeList = ExporterCacheManager.DummyHostCache.Find(element.Id);
                        foreach (KeyValuePair<ElementId, IFCRange> levelRange in levelRangeList)
                        {
                            rangeSetter.IncreaseRangeIndex();
                            IFCAnyHandle wallElemHnd = ExportDummyWall(exporterIFC, element, geometryElement, productWrapper, levelRange.Key, levelRange.Value);
                            if (!IFCAnyHandleUtil.IsNullOrHasNoValue(wallElemHnd))
                                createdWalls.Add(wallElemHnd);
                        }
                    }
                }
            }

            if (createdWalls.Count == 0)
                ExportWallBase(exporterIFC, element, connectedWalls, geometryElement, productWrapper, ElementId.InvalidElementId, null);
        }
        /// <summary>
        /// Exports a family instance to corresponding IFC object.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="familyInstance">
        /// The family instance to be exported.
        /// </param>
        /// <param name="geometryElement">
        /// The geometry element.
        /// </param>
        /// <param name="productWrapper">
        /// The ProductWrapper.
        /// </param>
        public static void ExportFamilyInstanceElement(ExporterIFC exporterIFC,
           FamilyInstance familyInstance, GeometryElement geometryElement, ProductWrapper productWrapper)
        {
            // Don't export family if it is invisible, or has a null geometry.
            if (familyInstance.Invisible || geometryElement == null)
                return;

            // Don't export family instance if it has a curtain grid host; the host will be in charge of exporting.
            Element host = familyInstance.Host;
            if (CurtainSystemExporter.IsCurtainSystem(host))
                return;

            FamilySymbol familySymbol = familyInstance.Symbol;
            Family family = familySymbol.Family;
            if (family == null)
                return;

            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                string ifcEnumType;
                IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, familyInstance, out ifcEnumType);

                if (exportType == IFCExportType.DontExport)
                    return;

                if (ExportFamilyInstanceAsStandardElement(exporterIFC, familyInstance, geometryElement, exportType, ifcEnumType, productWrapper))
                {
                    tr.Commit();
                    return;
                }

                // If we are exporting a column, we may need to split it into parts by level.  Create a list of ranges.
                IList<ElementId> levels = new List<ElementId>();
                IList<IFCRange> ranges = new List<IFCRange>();

                // We will not split walls and columns if the assemblyId is set, as we would like to keep the original wall
                // associated with the assembly, on the level of the assembly.
                bool splitColumn = (exportType == IFCExportType.IfcColumnType) && (ExporterCacheManager.ExportOptionsCache.WallAndColumnSplitting) &&
                    (familyInstance.AssemblyInstanceId == ElementId.InvalidElementId);
                if (splitColumn)
                {
                    LevelUtil.CreateSplitLevelRangesForElement(exporterIFC, exportType, familyInstance, out levels, out ranges);
                }

                int numPartsToExport = ranges.Count;
                if (numPartsToExport == 0)
                {
                    ExportFamilyInstanceAsMappedItem(exporterIFC, familyInstance, exportType, ifcEnumType, productWrapper,
                       ElementId.InvalidElementId, null, null);
                }
                else
                {
                    using (ExporterStateManager.RangeIndexSetter rangeSetter = new ExporterStateManager.RangeIndexSetter())
                    {
                        for (int ii = 0; ii < numPartsToExport; ii++)
                        {
                            rangeSetter.IncreaseRangeIndex();
                            ExportFamilyInstanceAsMappedItem(exporterIFC, familyInstance, exportType, ifcEnumType, productWrapper,
                              levels[ii], ranges[ii], null);
                        }
                    }

                    if (ExporterCacheManager.DummyHostCache.HasRegistered(familyInstance.Id))
                    {
                        using (ExporterStateManager.RangeIndexSetter rangeSetter = new ExporterStateManager.RangeIndexSetter())
                        {
                            List<KeyValuePair<ElementId, IFCRange>> levelRangeList = ExporterCacheManager.DummyHostCache.Find(familyInstance.Id);
                            foreach (KeyValuePair<ElementId, IFCRange> levelRange in levelRangeList)
                            {
                                rangeSetter.IncreaseRangeIndex();
                                ExportFamilyInstanceAsMappedItem(exporterIFC, familyInstance, exportType, ifcEnumType, productWrapper, levelRange.Key, levelRange.Value, null);
                            }
                        }
                    }
                }

                tr.Commit();
            }
        }