/// <summary>
        /// Collect information to create zones and cache them to create when end export.
        /// </summary>
        /// <param name="exporterIFC">The exporterIFC object.</param>
        /// <param name="file">The IFCFile object.</param>
        /// <param name="element">The element.</param>
        /// <param name="productWrapper">The ProductWrapper.</param>
        static void CreateZoneInfos(ExporterIFC exporterIFC, IFCFile file, Element element, ProductWrapper productWrapper)
        {
         bool exportToCOBIE = ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE;

            // Extra zone information, since Revit doesn't have architectural zones.
            int val = 0;
            string basePropZoneName = "ZoneName";
            string basePropZoneObjectType = "ZoneObjectType";
            string basePropZoneDescription = "ZoneDescription";
            string basePropZoneClassificationCode = "ZoneClassificationCode";

            // While a room may contain multiple zones, only one can have the extra parameters.  We will allow the first zone encountered
            // to be defined by them. If we require defining multiple zones in one room, then the code below should be modified to modify the 
            // names of the shared parameters to include the index of the appropriate room.
            bool exportedExtraZoneInformation = false;

            while (++val < 1000)   // prevent infinite loop.
            {
                string propZoneName, propZoneObjectType, propZoneDescription, propZoneClassificationCode;
                if (val == 1)
                {
                    propZoneName = basePropZoneName;
                    propZoneObjectType = basePropZoneObjectType;
                    propZoneDescription = basePropZoneDescription;
                    propZoneClassificationCode = basePropZoneClassificationCode;
                }
                else
                {
                    propZoneName = basePropZoneName + " " + val;
                    propZoneObjectType = basePropZoneObjectType + " " + val;
                    propZoneDescription = basePropZoneDescription + " " + val;
                    propZoneClassificationCode = basePropZoneClassificationCode + " " + val;
                }

                string zoneName;
                string zoneObjectType;
                string zoneDescription;
                string zoneClassificationCode;
                IFCAnyHandle zoneClassificationReference;

                if (ParameterUtil.GetOptionalStringValueFromElementOrSymbol(element, propZoneName, out zoneName) == null)
                    break;

                // If we have an empty zone name, but the value exists, keep looking to make sure there aren't valid values later.
                if (!String.IsNullOrEmpty(zoneName))
                {
                    Dictionary<string, IFCAnyHandle> classificationHandles = new Dictionary<string, IFCAnyHandle>();

                    ParameterUtil.GetStringValueFromElementOrSymbol(element, propZoneObjectType, out zoneObjectType);

                    ParameterUtil.GetStringValueFromElementOrSymbol(element, propZoneDescription, out zoneDescription);

                    ParameterUtil.GetStringValueFromElementOrSymbol(element, propZoneClassificationCode, out zoneClassificationCode);
                    string classificationName, classificationCode, classificationDescription;

                    if (!String.IsNullOrEmpty(zoneClassificationCode))
                    {
                        ClassificationUtil.parseClassificationCode(zoneClassificationCode, propZoneClassificationCode, out classificationName, out classificationCode, out classificationDescription);
                        string location = null;
                        ExporterCacheManager.ClassificationLocationCache.TryGetValue(classificationName, out location);
                        zoneClassificationReference = ClassificationUtil.CreateClassificationReference(file, classificationName, classificationCode, classificationDescription, location);
                        classificationHandles.Add(classificationName, zoneClassificationReference);
                    }

                    IFCAnyHandle roomHandle = productWrapper.GetElementOfType(IFCEntityType.IfcSpace);

                    IFCAnyHandle energyAnalysisPSetHnd = null;

                    if (exportToCOBIE && !exportedExtraZoneInformation)
                    {
                        exportedExtraZoneInformation = CreateGSAInformation(exporterIFC, element, zoneObjectType,
                            classificationHandles, energyAnalysisPSetHnd);
                    }

                    ZoneInfo zoneInfo = ExporterCacheManager.ZoneInfoCache.Find(zoneName);
                    if (zoneInfo == null)
                    {
                        IFCAnyHandle zoneCommonPropertySetHandle = CreateZoneCommonPSet(exporterIFC, file, element);
                        zoneInfo = new ZoneInfo(zoneObjectType, zoneDescription, roomHandle, classificationHandles, energyAnalysisPSetHnd, zoneCommonPropertySetHandle);
                        ExporterCacheManager.ZoneInfoCache.Register(zoneName, zoneInfo);
                    }
                    else
                    {
                        // if description and object type were empty, overwrite.
                        if (!String.IsNullOrEmpty(zoneObjectType) && String.IsNullOrEmpty(zoneInfo.ObjectType))
                            zoneInfo.ObjectType = zoneObjectType;
                        if (!String.IsNullOrEmpty(zoneDescription) && String.IsNullOrEmpty(zoneInfo.Description))
                            zoneInfo.Description = zoneDescription;

                        zoneInfo.RoomHandles.Add(roomHandle);
                        foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in classificationHandles)
                        {
                            if (!zoneInfo.ClassificationReferences[classificationReference.Key].HasValue)
                                zoneInfo.ClassificationReferences[classificationReference.Key] = classificationReference.Value;
                            else
                            {
                                // Delete redundant IfcClassificationReference from file.
                                classificationReference.Value.Delete();
                            }
                        }

                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(zoneInfo.EnergyAnalysisProperySetHandle))
                            zoneInfo.EnergyAnalysisProperySetHandle = energyAnalysisPSetHnd;
                        else if (energyAnalysisPSetHnd.HasValue)
                            energyAnalysisPSetHnd.Delete();

                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(zoneInfo.ZoneCommonProperySetHandle))
                            zoneInfo.ZoneCommonProperySetHandle = CreateZoneCommonPSet(exporterIFC, file, element);
                    }
                }
            }
        }
        /// <summary>
        /// Collect information to create space occupants and cache them to create when end export.
        /// </summary>
        /// <param name="exporterIFC">
        /// The exporterIFC object.
        /// </param>
        /// <param name="file">
        /// The IFCFile object.
        /// </param>
        /// <param name="element">
        /// The element.
        /// </param>
        /// <param name="productWrapper">
        /// The ProductWrapper.
        /// </param>
        static void CreateSpaceOccupantInfo(ExporterIFC exporterIFC, IFCFile file, Element element, ProductWrapper productWrapper)
        {
            IFCAnyHandle roomHandle = productWrapper.GetElementOfType(IFCEntityType.IfcSpace);

         bool exportToCOBIE = ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE;

            string name;
            if (ParameterUtil.GetStringValueFromElement(element.Id, "Occupant", out name) != null)
            {
                Dictionary<string, IFCAnyHandle> classificationHandles = new Dictionary<string, IFCAnyHandle>();

                // Classifications.
                if (exportToCOBIE)
                {
                    Document doc = element.Document;
                    ProjectInfo projectInfo = doc.ProjectInformation;

                    string location = null;
                    if (projectInfo != null)
                        ParameterUtil.GetStringValueFromElement(projectInfo.Id, "BIM Standards URL", out location);

                    string itemReference;
                    if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Organization ID Reference", out itemReference) != null)
                    {
                        string itemName;
                        ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Organization ID Name", out itemName);

                        IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file,
                          location, itemReference, itemName, null);
                        classificationHandles["Space Occupant Organization ID"] = classificationReference;
                    }

                    if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Sub-Organization ID Reference", out itemReference) != null)
                    {
                        string itemName;
                        ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Sub-Organization ID Name", out itemName);

                        IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file,
                          location, itemReference, itemName, null);
                        classificationHandles["Space Occupant Sub-Organization ID"] = classificationReference;
                    }

                    if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Sub-Organization ID Reference", out itemReference) != null)
                    {
                        string itemName;
                        ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Sub-Organization ID Name", out itemName);

                        IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file,
                          location, itemReference, itemName, null);
                        classificationHandles["Space Occupant Sub-Organization ID"] = classificationReference;
                    }

                    if (ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Organization Billing ID Reference", out itemReference) != null)
                    {
                        string itemName;
                        ParameterUtil.GetStringValueFromElementOrSymbol(element, "Space Occupant Organization Billing ID Name", out itemName);

                        IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file,
                          location, itemReference, itemName, null);
                        classificationHandles["Space Occupant Organization Billing ID"] = classificationReference;
                    }
                }

                // Look for Parameter Set definition.  We don't use the general approach as Space Occupants are not "real" elements.
                IFCAnyHandle spaceOccupantPSetHnd = CreatePSetSpaceOccupant(exporterIFC, file, element);

                SpaceOccupantInfo spaceOccupantInfo = ExporterCacheManager.SpaceOccupantInfoCache.Find(name);
                if (spaceOccupantInfo == null)
                {
                    spaceOccupantInfo = new SpaceOccupantInfo(roomHandle, classificationHandles, spaceOccupantPSetHnd);
                    ExporterCacheManager.SpaceOccupantInfoCache.Register(name, spaceOccupantInfo);
                }
                else
                {
                    spaceOccupantInfo.RoomHandles.Add(roomHandle);
                    foreach (KeyValuePair<string, IFCAnyHandle> classificationReference in classificationHandles)
                    {
                        if (!spaceOccupantInfo.ClassificationReferences[classificationReference.Key].HasValue)
                            spaceOccupantInfo.ClassificationReferences[classificationReference.Key] = classificationReference.Value;
                        else
                        {
                            // Delete redundant IfcClassificationReference from file.
                            classificationReference.Value.Delete();
                        }
                    }

                    if (spaceOccupantInfo.SpaceOccupantProperySetHandle == null || !spaceOccupantInfo.SpaceOccupantProperySetHandle.HasValue)
                        spaceOccupantInfo.SpaceOccupantProperySetHandle = spaceOccupantPSetHnd;
                    else if (spaceOccupantPSetHnd.HasValue)
                        spaceOccupantPSetHnd.Delete();
                }
            }
        }