void AddPsetDefToDict(string schemaVersionName, PsetDefinition psetD)
        {
            VersionSpecificPropertyDef psetDefEntry = new VersionSpecificPropertyDef()
            {
                SchemaFileVersion = schemaVersionName,
                IfcVersion        = psetD.IfcVersion,
                PropertySetDef    = psetD
            };

            if (allPDefDict.ContainsKey(psetD.Name))
            {
                allPDefDict[psetD.Name].Add(psetDefEntry);
            }
            else
            {
                IList <VersionSpecificPropertyDef> vsPropDefList = new List <VersionSpecificPropertyDef>();
                vsPropDefList.Add(psetDefEntry);
                allPDefDict.Add(psetD.Name, vsPropDefList);
            }
        }
        public void processSimpleProperty(StreamWriter outF, PsetProperty prop, string propNamePrefix, string IfcVersion, string schemaVersion,
                                          string varName, VersionSpecificPropertyDef vSpecPDef, string outputFile)
        {
            outF.WriteLine("\t\t\t\tifcPSE = new PropertySetEntry(\"{0}\");", prop.Name);
            outF.WriteLine("\t\t\t\tifcPSE.PropertyName = \"{0}\";", prop.Name);
            if (prop.PropertyType != null)
            {
                if (prop.PropertyType is PropertyEnumeratedValue)
                {
                    PropertyEnumeratedValue propEnum = prop.PropertyType as PropertyEnumeratedValue;
                    outF.WriteLine("\t\t\t\tifcPSE.PropertyType = PropertyType.Label;");
                    outF.WriteLine("\t\t\t\tifcPSE.PropertyValueType = PropertyValueType.EnumeratedValue;");
                    outF.WriteLine("\t\t\t\tifcPSE.PropertyEnumerationType = typeof(Revit.IFC.Export.Exporter.PropertySet." + IfcVersion + "." + propEnum.Name + ");");
                    IList <string> enumItems = new List <string>();
                    foreach (PropertyEnumItem enumItem in propEnum.EnumDef)
                    {
                        string item = HandleInvalidCharacter(enumItem.EnumItem);
                        enumItems.Add(item);
                    }
                    writeEnumFile(IfcVersion, schemaVersion, propEnum.Name, enumItems, outputFile);
                }
                else if (prop.PropertyType is PropertyReferenceValue)
                {
                    PropertyReferenceValue propRef = prop.PropertyType as PropertyReferenceValue;
                    outF.WriteLine("\t\t\t\tifcPSE.PropertyType = PropertyType.{0};", propRef.RefEntity.Trim());
                    outF.WriteLine("\t\t\t\tifcPSE.PropertyValueType = PropertyValueType.ReferenceValue;");
                }
                else if (prop.PropertyType is PropertyListValue)
                {
                    PropertyListValue propList = prop.PropertyType as PropertyListValue;
                    if (propList.DataType != null && !propList.DataType.Equals("IfcValue", StringComparison.InvariantCultureIgnoreCase))
                    {
                        outF.WriteLine("\t\t\t\tifcPSE.PropertyType = PropertyType.{0};", propList.DataType.ToString().Replace("Ifc", "").Replace("Measure", "").Trim());
                    }
                    else
                    {
                        outF.WriteLine("\t\t\t\tifcPSE.PropertyType = PropertyType.Label;"); // default to Label if not defined
                    }
                    outF.WriteLine("\t\t\t\tifcPSE.PropertyValueType = PropertyValueType.ListValue;");
                }
                else if (prop.PropertyType is PropertyTableValue)
                {
                    PropertyTableValue propTab = prop.PropertyType as PropertyTableValue;
                    // TableValue has 2 types: DefiningValue and DefinedValue. This is not fully implemented yet
                    if (propTab.DefinedValueType != null)
                    {
                        outF.WriteLine("\t\t\t\tifcPSE.PropertyType = PropertyType.{0};", propTab.DefinedValueType.ToString().Replace("Ifc", "").Replace("Measure", "").Trim());
                    }
                    else
                    {
                        outF.WriteLine("\t\t\t\tifcPSE.PropertyType = PropertyType.Label;"); // default to Label if missing
                    }
                    outF.WriteLine("\t\t\t\tifcPSE.PropertyValueType = PropertyValueType.TableValue;");
                }
                else
                {
                    outF.WriteLine("\t\t\t\tifcPSE.PropertyType = PropertyType.{0};", prop.PropertyType.ToString().Replace("Ifc", "").Replace("Measure", "").Trim());
                }
            }
            else
            {
                prop.PropertyType = new PropertySingleValue();
                // Handle bad cases where datatype is somehow missing in the PSD
                if (prop.Name.ToLowerInvariant().Contains("ratio") ||
                    prop.Name.ToLowerInvariant().Contains("length") ||
                    prop.Name.ToLowerInvariant().Contains("width") ||
                    prop.Name.ToLowerInvariant().Contains("thickness") ||
                    prop.Name.ToLowerInvariant().Contains("angle") ||
                    prop.Name.ToLowerInvariant().Contains("transmittance") ||
                    prop.Name.ToLowerInvariant().Contains("fraction") ||
                    prop.Name.ToLowerInvariant().Contains("rate") ||
                    prop.Name.ToLowerInvariant().Contains("velocity") ||
                    prop.Name.ToLowerInvariant().Contains("speed") ||
                    prop.Name.ToLowerInvariant().Contains("capacity") ||
                    prop.Name.ToLowerInvariant().Contains("pressure") ||
                    prop.Name.ToLowerInvariant().Contains("temperature") ||
                    prop.Name.ToLowerInvariant().Contains("power") ||
                    prop.Name.ToLowerInvariant().Contains("heatgain") ||
                    prop.Name.ToLowerInvariant().Contains("efficiency") ||
                    prop.Name.ToLowerInvariant().Contains("resistance") ||
                    prop.Name.ToLowerInvariant().Contains("coefficient") ||
                    prop.Name.ToLowerInvariant().Contains("measure"))
                {
                    (prop.PropertyType as PropertySingleValue).DataType = "IfcReal";
                }
                else if (prop.Name.ToLowerInvariant().Contains("loadbearing"))
                {
                    (prop.PropertyType as PropertySingleValue).DataType = "IfcBoolean";
                }
                else
                {
                    (prop.PropertyType as PropertySingleValue).DataType = "IfcLabel";
                }
#if DEBUG
                logF.WriteLine("%Warning: " + prop.Name + " from " + vSpecPDef.PropertySetDef.Name + "(" + vSpecPDef.SchemaFileVersion + ") is missing PropertyType/datatype. Set to default "
                               + (prop.PropertyType as PropertySingleValue).DataType);
#endif
            }

            // Append new definition to the Shared parameter file
            SharedParameterDef newPar = new SharedParameterDef();
            newPar.Name = prop.Name;

            // Use IfdGuid for the GUID if defined
            Guid pGuid      = Guid.Empty;
            bool hasIfdGuid = false;
            if (!string.IsNullOrEmpty(prop.IfdGuid))
            {
                if (Guid.TryParse(prop.IfdGuid, out pGuid))
                {
                    hasIfdGuid = true;
                }
            }
            if (pGuid == Guid.Empty)
            {
                pGuid = Guid.NewGuid();
            }

            newPar.ParamGuid = pGuid;

            if (prop.PropertyType != null)
            {
                newPar.Description = prop.PropertyType.ToString().Split(' ', '\t')[0].Trim(); // Put the original IFC datatype in the description
            }
            else
            {
#if DEBUG
                logF.WriteLine("%Warning: " + prop.Name + " from " + vSpecPDef.PropertySetDef.Name + "(" + vSpecPDef.SchemaFileVersion + ") is missing PropertyType/datatype.");
#endif
            }

            if (prop.PropertyType is PropertyEnumeratedValue)
            {
                newPar.ParamType = "TEXT"; // Support only a single enum value (which is most if not all cases known)
            }
            else if (prop.PropertyType is PropertyReferenceValue ||
                     prop.PropertyType is PropertyBoundedValue ||
                     prop.PropertyType is PropertyListValue ||
                     prop.PropertyType is PropertyTableValue)
            {
                // For all the non-simple value, a TEXT parameter will be created that will contain formatted string
                newPar.ParamType = "MULTILINETEXT";
                if (prop.PropertyType is PropertyBoundedValue)
                {
                    newPar.Description = "PropertyBoundedValue"; // override the default to the type of property datatype
                }
                else if (prop.PropertyType is PropertyListValue)
                {
                    newPar.Description = "PropertyListValue"; // override the default to the type of property datatype
                }
                else if (prop.PropertyType is PropertyTableValue)
                {
                    newPar.Description = "PropertyTableValue"; // override the default to the type of property datatype
                }
            }
            else if (prop.PropertyType is PropertySingleValue)
            {
                PropertySingleValue propSingle = prop.PropertyType as PropertySingleValue;
                newPar.Description = propSingle.DataType; // Put the original IFC datatype in the description

                if (propSingle.DataType.Equals("IfcPositivePlaneAngleMeasure", StringComparison.InvariantCultureIgnoreCase) ||
                    propSingle.DataType.Equals("IfcSolidAngleMeasure", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "ANGLE";
                }
                else if (propSingle.DataType.Equals("IfcAreaMeasure", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "AREA";
                }
                else if (propSingle.DataType.Equals("IfcMonetaryMeasure", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "CURRENCY";
                }
                else if (propSingle.DataType.Equals("IfcPositivePlaneAngleMeasure", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcCardinalPointReference", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcCountMeasure", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcDayInMonthNumber", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcDayInWeekNumber", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcDimensionCount", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcInteger", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcIntegerCountRateMeasure", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcMonthInYearNumber", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcTimeStamp", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "INTEGER";
                }
                else if (propSingle.DataType.Equals("IfcLengthMeasure", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcNonNegativeLengthMeasure", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcPositiveLengthMeasure", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "LENGTH";
                }
                else if (propSingle.DataType.Equals("IfcMassDensityMeasure", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "MASS_DENSITY";
                }
                else if (propSingle.DataType.Equals("IfcArcIndex", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcComplexNumber", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcCompoundPlaneAngleMeasure", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcLineIndex", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcPropertySetDefinitionSet", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "MULTILINETEXT";
                }
                else if (propSingle.DataType.Equals("IfcBinary", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcBoxAlignment", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcDate", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcDateTime", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcDescriptiveMeasure", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcDuration", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcFontStyle", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcFontVariant", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcFontWeight", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcGloballyUniqueId", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcIdentifier", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcLabel", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcLanguageId", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcPresentableText", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcText", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcTextAlignment", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcTextDecoration", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcTextFontName", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcTextTransformation", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcTime", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "TEXT";
                }
                else if (propSingle.DataType.Equals("IfcURIReference", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "URL";
                }
                else if (propSingle.DataType.Equals("IfcVolumeMeasure", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "VOLUME";
                }
                else if (propSingle.DataType.Equals("IfcBoolean", StringComparison.InvariantCultureIgnoreCase) ||
                         propSingle.DataType.Equals("IfcLogical", StringComparison.InvariantCultureIgnoreCase))
                {
                    newPar.ParamType = "YESNO";
                }
                else
                {
                    newPar.ParamType = "NUMBER";
                }
            }

            if (!SharedParamFileDict.ContainsKey(newPar.Name))
            {
                SharedParamFileDict.Add(newPar.Name, newPar);
            }
            else // Keep the GUID, but override the details
            {
                // If this Property has IfcGuid, use the IfdGuid set in the newPar, otherwise keep the original one
                if (!hasIfdGuid)
                {
                    newPar.ParamGuid = SharedParamFileDict[newPar.Name].ParamGuid;
                }
                SharedParamFileDict[newPar.Name] = newPar; // override the Dict
            }

            SharedParameterDef newParType = (SharedParameterDef)newPar.Clone();
            newParType.Name = newParType.Name + "[Type]";
            if (!SharedParamFileTypeDict.ContainsKey(newParType.Name))
            {
                SharedParamFileTypeDict.Add(newParType.Name, newParType);
            }
            else // Keep the GUID, but override the details
            {
                newParType.ParamGuid = SharedParamFileTypeDict[newParType.Name].ParamGuid;
                SharedParamFileTypeDict[newParType.Name] = newParType; // override the Dict
            }

            if (prop.NameAliases != null)
            {
                foreach (NameAlias alias in prop.NameAliases)
                {
                    LanguageType lang = checkAliasLanguage(alias.lang);
                    outF.WriteLine("\t\t\t\tifcPSE.AddLocalizedParameterName(LanguageType.{0}, \"{1}\");", lang, alias.Alias);
                }
            }

            string calcName = "Revit.IFC.Export.Exporter.PropertySet.Calculators." + prop.Name + "Calculator";
            outF.WriteLine("\t\t\t\tcalcType = System.Reflection.Assembly.GetExecutingAssembly().GetType(\"" + calcName + "\");");
            outF.WriteLine("\t\t\t\tif (calcType != null)");
            outF.WriteLine("\t\t\t\t\tifcPSE.PropertyCalculator = (PropertyCalculator) calcType.GetConstructor(Type.EmptyTypes).Invoke(new object[]{});");
            outF.WriteLine("\t\t\t\t{0}.AddEntry(ifcPSE);", varName);
            outF.WriteLine("");
        }