public virtual object Clone()
        {
            SharedParameterDef clonePar = new SharedParameterDef();

            clonePar.Param          = this.Param;
            clonePar.ParamGuid      = this.ParamGuid;
            clonePar.Name           = this.Name;
            clonePar.ParamType      = this.ParamType;
            clonePar.DataCategory   = this.DataCategory;
            clonePar.GroupId        = this.GroupId;
            clonePar.Visibility     = this.Visibility;
            clonePar.Description    = this.Description;
            clonePar.UserModifiable = this.UserModifiable;
            return(clonePar);
        }
Ejemplo n.º 2
0
        private void button_Go_Click(object sender, RoutedEventArgs e)
        {
#if DEBUG
            string tempFolder = System.IO.Path.GetTempPath();
            logF = new StreamWriter(Path.Combine(tempFolder, "GeneratePsetDefWin.log"));
#endif
            textBox_OutputMsg.Clear();

            string parFileNameOut = Path.Combine(Path.GetDirectoryName(SharedParFileName), Path.GetFileNameWithoutExtension(SharedParFileName) + "_out.txt");
            stSharedPar = File.CreateText(parFileNameOut);
            ProcessPsetDefinition.processExistingParFile(SharedParFileName, false, ref stSharedPar);

            if (File.Exists(SharedParFileNameType))
            {
                string typeParFileNameOut = Path.Combine(Path.GetDirectoryName(SharedParFileNameType), Path.GetFileNameWithoutExtension(SharedParFileNameType) + "_out.txt");
                stSharedParType = File.CreateText(typeParFileNameOut);
                ProcessPsetDefinition.processExistingParFile(SharedParFileNameType, true, ref stSharedParType);
            }
            else
            {
                stSharedParType = File.CreateText(SharedParFileNameType);
            }

            ProcessPsetDefinition procPsetDef = new ProcessPsetDefinition(logF);

            if (string.IsNullOrEmpty(textBox_PSDSourceDir.Text) || string.IsNullOrEmpty(textBox_OutputFile.Text))
            {
                return;
            }

            var psdFolders = new DirectoryInfo(textBox_PSDSourceDir.Text).GetDirectories("psd", SearchOption.AllDirectories);

            string dirName       = Path.GetDirectoryName(textBox_OutputFile.Text);
            string penumFileName = Path.GetFileNameWithoutExtension(textBox_OutputFile.Text);

            if (File.Exists(textBox_OutputFile.Text))
            {
                File.Delete(textBox_OutputFile.Text);
            }

            StreamWriter outF = new StreamWriter(textBox_OutputFile.Text);
            outF.WriteLine("/********************************************************************************************************************************");
            outF.WriteLine("** NOTE: This code is generated from IFC psd files automatically by RevitIFCTools.                                            **");
            outF.WriteLine("**       DO NOT change it manually as it will be overwritten the next time this file is re-generated!!                        **");
            outF.WriteLine("********************************************************************************************************************************/");
            outF.WriteLine();
            outF.WriteLine("using System;");
            outF.WriteLine("using System.Collections.Generic;");
            outF.WriteLine("using System.Linq;");
            outF.WriteLine("using System.Text;");
            outF.WriteLine("using System.Threading.Tasks;");
            outF.WriteLine("using Autodesk.Revit;");
            outF.WriteLine("using Autodesk.Revit.DB;");
            outF.WriteLine("using Autodesk.Revit.DB.IFC;");
            outF.WriteLine("using Autodesk.Revit.ApplicationServices;");
            outF.WriteLine("using Revit.IFC.Export.Exporter.PropertySet;");
            outF.WriteLine("using Revit.IFC.Export.Exporter.PropertySet.Calculators;");
            outF.WriteLine("using Revit.IFC.Export.Utility;");
            outF.WriteLine("using Revit.IFC.Export.Toolkit;");
            outF.WriteLine("using Revit.IFC.Common.Enums;");
            outF.WriteLine("");
            outF.WriteLine("namespace Revit.IFC.Export.Exporter");
            outF.WriteLine("{");
            outF.WriteLine("\tpartial class ExporterInitializer");
            outF.WriteLine("\t{");

            // Collect all Pset definition for psd folders
            foreach (DirectoryInfo psd in psdFolders)
            {
                string schemaFolder = psd.FullName.Remove(0, textBox_PSDSourceDir.Text.Length + 1).Split('\\')[0];

#if DEBUG
                logF.WriteLine("\n*** Processing " + schemaFolder);
#endif
                foreach (DirectoryInfo subDir in psd.GetDirectories())
                {
                    procPsetDef.ProcessSchemaPsetDef(schemaFolder, subDir);
                }
                procPsetDef.ProcessSchemaPsetDef(schemaFolder, psd);
            }

            // For testing purpose: Dump all the propertyset definition in a text file
            if (checkBox_Dump.IsChecked.HasValue && checkBox_Dump.IsChecked.Value)
            {
                string pSetDump = "";
                foreach (KeyValuePair <string, IList <VersionSpecificPropertyDef> > psetDefEntry in procPsetDef.allPDefDict)
                {
                    pSetDump += "**** Property Set Name: " + psetDefEntry.Key;
                    foreach (VersionSpecificPropertyDef vPdef in psetDefEntry.Value)
                    {
                        pSetDump += "\n  ===> IfcVersion: " + vPdef.IfcVersion;
                        pSetDump += "\n" + vPdef.PropertySetDef.ToString() + "\n";
                    }
                    pSetDump += "\n\n";
                }
                string dumpDir      = Path.GetDirectoryName(textBox_OutputFile.Text);
                string dumpFile     = Path.GetFileNameWithoutExtension(textBox_OutputFile.Text) + ".txt";
                string dumpFilePath = Path.Combine(dumpDir, dumpFile);

                if (File.Exists(dumpFilePath))
                {
                    File.Delete(dumpFilePath);
                }

                StreamWriter tx = new StreamWriter(dumpFilePath);
                tx.Write(pSetDump);
                tx.Close();
            }

            // Method to initialize all the propertysets
            outF.WriteLine("\t\tpublic static void InitCommonPropertySets(IList<IList<PropertySetDescription>> propertySets)");
            outF.WriteLine("\t\t{");
            outF.WriteLine("\t\t\tIList<PropertySetDescription> commonPropertySets = new List<PropertySetDescription>();");
            foreach (KeyValuePair <string, IList <VersionSpecificPropertyDef> > psetDefEntry in procPsetDef.allPDefDict)
            {
                outF.WriteLine("\t\t\tInit" + psetDefEntry.Key + "(commonPropertySets);");
            }
            outF.WriteLine("\n\t\t\tpropertySets.Add(commonPropertySets);");
            outF.WriteLine("\t\t}");
            outF.WriteLine("");

            // For generated codes and shared parameters
            foreach (KeyValuePair <string, IList <VersionSpecificPropertyDef> > psetDefEntry in procPsetDef.allPDefDict)
            {
                string psetName = psetDefEntry.Key;
                outF.WriteLine("\t\tprivate static void Init" + psetName + "(IList<PropertySetDescription> commonPropertySets)");
                outF.WriteLine("\t\t{");

                string varName = psetDefEntry.Key.Replace("Pset_", "propertySet");

                outF.WriteLine("\t\t\tPropertySetDescription {0} = new PropertySetDescription();", varName);

                string psetEnumStr = psetName.Replace("PSet_", "PSet");
                try
                {
                    Revit.IFC.Export.Toolkit.IFCCommonPSets psetEnum = (Revit.IFC.Export.Toolkit.IFCCommonPSets)Enum.Parse(typeof(Revit.IFC.Export.Toolkit.IFCCommonPSets), psetEnumStr);
                    outF.WriteLine("\t\t\t{0}.SubElementIndex = (int)IFCCommonPSets.{1};", varName, psetName.Replace("PSet_", "PSet"));
                }
                catch (ArgumentException)
                {
#if DEBUG
                    logF.WriteLine("\t%Info: " + psetEnumStr + " is not defined in Revit.IFC.Export.Toolkit.IFCCommonPSets.");
#endif
                }

                outF.WriteLine("\t\t\t{0}.Name = \"{1}\";", varName, psetName);
                outF.WriteLine("\t\t\tPropertySetEntry ifcPSE = null;");
                outF.WriteLine("\t\t\tType calcType = null;");

                foreach (VersionSpecificPropertyDef vspecPDef in psetDefEntry.Value)
                {
                    PsetDefinition pDef = vspecPDef.PropertySetDef;

                    if (vspecPDef.IfcVersion.Equals("IFC2X2", StringComparison.CurrentCultureIgnoreCase))
                    {
                        outF.WriteLine("\t\t\tif (ExporterCacheManager.ExportOptionsCache.ExportAs2x2 && certifiedEntityAndPsetList.AllowPsetToBeCreated(ExporterCacheManager.ExportOptionsCache.FileVersion.ToString().ToUpper(), \"" + psetName + "\"))");
                        outF.WriteLine("\t\t\t{");
                        foreach (string applEnt in vspecPDef.PropertySetDef.ApplicableClasses)
                        {
                            string applEnt2 = applEnt;
                            if (string.IsNullOrEmpty(applEnt))
                            {
                                applEnt2 = "IfcBuildingElementProxy"; // Default if somehow the data is empty
                            }
                            outF.WriteLine("\t\t\t\t{0}.EntityTypes.Add(IFCEntityType.{1});", varName, applEnt2);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.ApplicableType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.ObjectType = \"{1}\";", varName, vspecPDef.PropertySetDef.ApplicableType);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.PredefinedType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.PredefinedType = \"{1}\";", varName, vspecPDef.PropertySetDef.PredefinedType);
                        }
                    }
                    else if (vspecPDef.IfcVersion.Equals("IFC2X3TC1", StringComparison.CurrentCultureIgnoreCase) ||
                             vspecPDef.IfcVersion.Equals("IFC2X3_TC1", StringComparison.CurrentCultureIgnoreCase))
                    {
                        outF.WriteLine("\t\t\tif (ExporterCacheManager.ExportOptionsCache.ExportAs2x3 && certifiedEntityAndPsetList.AllowPsetToBeCreated(ExporterCacheManager.ExportOptionsCache.FileVersion.ToString().ToUpper(), \"" + psetName + "\"))");
                        outF.WriteLine("\t\t\t{");
                        foreach (string applEnt in vspecPDef.PropertySetDef.ApplicableClasses)
                        {
                            string applEnt2 = applEnt;
                            if (string.IsNullOrEmpty(applEnt))
                            {
                                applEnt2 = "IfcBuildingElementProxy"; // Default if somehow the data is empty
                            }
                            outF.WriteLine("\t\t\t\t{0}.EntityTypes.Add(IFCEntityType.{1});", varName, applEnt2);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.ApplicableType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.ObjectType = \"{1}\";", varName, vspecPDef.PropertySetDef.ApplicableType);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.PredefinedType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.PredefinedType = \"{1}\";", varName, vspecPDef.PropertySetDef.PredefinedType);
                        }
                    }
                    //else if (vspecPDef.IfcVersion.Equals("IFC4_ADD1"))
                    //{
                    else if (vspecPDef.SchemaFileVersion.Equals("IFC4_ADD1", StringComparison.CurrentCultureIgnoreCase))
                    {
                        outF.WriteLine("\t\t\tif (ExporterCacheManager.ExportOptionsCache.ExportAs4_ADD1 && certifiedEntityAndPsetList.AllowPsetToBeCreated(ExporterCacheManager.ExportOptionsCache.FileVersion.ToString().ToUpper(), \"" + psetName + "\"))");
                        outF.WriteLine("\t\t\t{");
                        foreach (string applEnt in vspecPDef.PropertySetDef.ApplicableClasses)
                        {
                            string applEnt2 = applEnt;
                            if (string.IsNullOrEmpty(applEnt))
                            {
                                applEnt2 = "IfcBuildingElementProxy"; // Default if somehow the data is empty
                            }
                            outF.WriteLine("\t\t\t\t{0}.EntityTypes.Add(IFCEntityType.{1});", varName, applEnt2);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.ApplicableType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.ObjectType = \"{1}\";", varName, vspecPDef.PropertySetDef.ApplicableType);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.PredefinedType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.PredefinedType = \"{1}\";", varName, vspecPDef.PropertySetDef.PredefinedType);
                        }
                    }
                    else if (vspecPDef.SchemaFileVersion.Equals("IFC4_ADD2", StringComparison.CurrentCultureIgnoreCase))
                    {
                        outF.WriteLine("\t\t\tif (ExporterCacheManager.ExportOptionsCache.ExportAs4_ADD2 && certifiedEntityAndPsetList.AllowPsetToBeCreated(ExporterCacheManager.ExportOptionsCache.FileVersion.ToString().ToUpper(), \"" + psetName + "\"))");
                        outF.WriteLine("\t\t\t{");
                        foreach (string applEnt in vspecPDef.PropertySetDef.ApplicableClasses)
                        {
                            string applEnt2 = applEnt;
                            if (string.IsNullOrEmpty(applEnt))
                            {
                                applEnt2 = "IfcBuildingElementProxy"; // Default if somehow the data is empty
                            }
                            outF.WriteLine("\t\t\t\t{0}.EntityTypes.Add(IFCEntityType.{1});", varName, applEnt2);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.ApplicableType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.ObjectType = \"{1}\";", varName, vspecPDef.PropertySetDef.ApplicableType);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.PredefinedType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.PredefinedType = \"{1}\";", varName, vspecPDef.PropertySetDef.PredefinedType);
                        }
                    }
                    else if (vspecPDef.SchemaFileVersion.Equals("IFC4", StringComparison.CurrentCultureIgnoreCase))
                    {
                        outF.WriteLine("\t\t\tif (ExporterCacheManager.ExportOptionsCache.ExportAs4 && certifiedEntityAndPsetList.AllowPsetToBeCreated(ExporterCacheManager.ExportOptionsCache.FileVersion.ToString().ToUpper(), \"" + psetName + "\"))");
                        outF.WriteLine("\t\t\t{");
                        foreach (string applEnt in vspecPDef.PropertySetDef.ApplicableClasses)
                        {
                            string applEnt2 = applEnt;
                            if (string.IsNullOrEmpty(applEnt))
                            {
                                applEnt2 = "IfcBuildingElementProxy"; // Default if somehow the data is empty
                            }
                            outF.WriteLine("\t\t\t\t{0}.EntityTypes.Add(IFCEntityType.{1});", varName, applEnt2);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.ApplicableType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.ObjectType = \"{1}\";", varName, vspecPDef.PropertySetDef.ApplicableType);
                        }
                        if (!string.IsNullOrEmpty(vspecPDef.PropertySetDef.PredefinedType))
                        {
                            outF.WriteLine("\t\t\t\t{0}.PredefinedType = \"{1}\";", varName, vspecPDef.PropertySetDef.PredefinedType);
                        }
                    }
                    else
                    {
#if DEBUG
                        logF.WriteLine("%Error - Unrecognized schema version : " + vspecPDef.SchemaFileVersion);
#endif
                    }
                    //}

                    // Process each property
                    foreach (PsetProperty prop in pDef.properties)
                    {
                        // Handle only one level deep of complex property !!!!
                        if (prop.PropertyType is ComplexProperty)
                        {
                            ComplexProperty complexProp = prop.PropertyType as ComplexProperty;
                            // For complex property the properties will be flattened by using <Pset>.<Property>.<SubProperty>
                            foreach (PsetProperty propCx in complexProp.Properties)
                            {
                                string prefixName = pDef.Name + "." + prop.Name;
                                procPsetDef.processSimpleProperty(outF, propCx, prefixName, pDef.IfcVersion, vspecPDef.SchemaFileVersion, varName, vspecPDef, penumFileName);
                            }
                        }
                        else
                        {
                            procPsetDef.processSimpleProperty(outF, prop, pDef.Name, pDef.IfcVersion, vspecPDef.SchemaFileVersion, varName, vspecPDef, penumFileName);
                        }
                    }
                    outF.WriteLine("\t\t\t}");
                }

                outF.WriteLine("\t\t\tif (ifcPSE != null)");
                outF.WriteLine("\t\t\t{");
                //outF.WriteLine("\t\t\t\t{0}.Name = \"{1}\";", varName, psetName);
                outF.WriteLine("\t\t\t\tcommonPropertySets.Add({0});", varName);
                outF.WriteLine("\t\t\t}");
                outF.WriteLine("\t\t}");
                outF.WriteLine("\n");
            }

            outF.WriteLine("\t}");
            outF.WriteLine("}");
            outF.Close();
            procPsetDef.endWriteEnumFile();

            // Now write shared parameter definitions from the Dict to destination file
            stSharedPar.WriteLine("# This is a Revit shared parameter file.");
            stSharedPar.WriteLine("# Do not edit manually.");
            stSharedPar.WriteLine("*META	VERSION	MINVERSION");
            stSharedPar.WriteLine("META	2	1");
            stSharedPar.WriteLine("*GROUP	ID	NAME");
            stSharedPar.WriteLine("GROUP	2	IFC Properties");
            stSharedPar.WriteLine("*PARAM	GUID	NAME	DATATYPE	DATACATEGORY	GROUP	VISIBLE	DESCRIPTION	USERMODIFIABLE");
            stSharedPar.WriteLine("#");
            foreach (KeyValuePair <string, SharedParameterDef> parDef in ProcessPsetDefinition.SharedParamFileDict)
            {
                SharedParameterDef newPar = parDef.Value;
                string             vis    = newPar.Visibility ? "1" : "0";
                string             usrMod = newPar.UserModifiable ? "1" : "0";

                string parEntry = newPar.Param + "\t" + newPar.ParamGuid.ToString() + "\t" + newPar.Name + "\t" + newPar.ParamType + "\t" + newPar.DataCategory + "\t" + newPar.GroupId.ToString()
                                  + "\t" + vis + "\t" + newPar.Description + "\t" + usrMod;
                stSharedPar.WriteLine(parEntry);
            }

            stSharedParType.WriteLine("# This is a Revit shared parameter file.");
            stSharedParType.WriteLine("# Do not edit manually.");
            stSharedParType.WriteLine("*META	VERSION	MINVERSION");
            stSharedParType.WriteLine("META	2	1");
            stSharedParType.WriteLine("*GROUP	ID	NAME");
            stSharedParType.WriteLine("GROUP	2	IFC Properties");
            stSharedParType.WriteLine("*PARAM	GUID	NAME	DATATYPE	DATACATEGORY	GROUP	VISIBLE	DESCRIPTION	USERMODIFIABLE");
            stSharedParType.WriteLine("#");
            foreach (KeyValuePair <string, SharedParameterDef> parDef in ProcessPsetDefinition.SharedParamFileTypeDict)
            {
                SharedParameterDef newPar = parDef.Value;
                string             parName4Type;
                if (newPar.Name.EndsWith("[Type]"))
                {
                    parName4Type = newPar.Name;
                }
                else
                {
                    parName4Type = newPar.Name + "[Type]";
                }
                string vis    = newPar.Visibility ? "1" : "0";
                string usrMod = newPar.UserModifiable ? "1" : "0";

                string parEntry = newPar.Param + "\t" + newPar.ParamGuid.ToString() + "\t" + parName4Type + "\t" + newPar.ParamType + "\t" + newPar.DataCategory + "\t" + newPar.GroupId.ToString()
                                  + "\t" + vis + "\t" + newPar.Description + "\t" + usrMod;
                stSharedParType.WriteLine(parEntry);
            }

            stSharedPar.Close();
            stSharedParType.Close();
#if DEBUG
            logF.Close();
#endif
        }
Ejemplo n.º 3
0
        void WriteRevitSharedParam(StreamWriter stSharedPar, IDictionary <string, SharedParameterDef> existingParDict,
                                   IDictionary <string, int> groupParamDict, bool isType, out IList <string> deferredParList)
        {
            // Now write shared parameter definitions from the Dict to destination file
            stSharedPar.WriteLine("# This is a Revit shared parameter file.");
            stSharedPar.WriteLine("# Do not edit manually.");
            stSharedPar.WriteLine("*META	VERSION	MINVERSION");
            stSharedPar.WriteLine("META	2	1");
            stSharedPar.WriteLine("*GROUP	ID	NAME");
            int groupID = groupParamDict["Revit IFCExporter Parameters"];

            // Keep the list of Parameters that do not belong to any Pset to be written all together in one group at the end
            deferredParList = new List <string>();
            deferredParList.Add(string.Format("#"));
            deferredParList.Add(string.Format("GROUP	{0}	Revit IFCExporter Parameters", groupID));
            deferredParList.Add(string.Format("*PARAM	GUID	NAME	DATATYPE	DATACATEGORY	GROUP	VISIBLE	DESCRIPTION	USERMODIFIABLE"));
            deferredParList.Add(string.Format("#"));

            string prevPsetName   = "Revit IFCExporter Parameters";
            int    defaultGroupID = groupParamDict[prevPsetName];
            SortedDictionary <string, SharedParameterDef> SharedParDict = null;

            if (!isType)
            {
                SharedParDict = ProcessPsetDefinition.SharedParamFileDict;
            }
            else
            {
                SharedParDict = ProcessPsetDefinition.SharedParamFileTypeDict;
            }

            foreach (KeyValuePair <string, SharedParameterDef> parDef in ProcessPsetDefinition.SharedParamFileDict)
            {
                SharedParameterDef newPar = parDef.Value;
                bool toBeDeferred         = false;
                if (!prevPsetName.Equals(newPar.OwningPset, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (!string.IsNullOrEmpty(newPar.OwningPset))
                    {
                        prevPsetName = newPar.OwningPset;
                        groupID      = groupParamDict[newPar.OwningPset];
                        stSharedPar.WriteLine("#");
                        stSharedPar.WriteLine("GROUP	{0}	{1}", groupID, newPar.OwningPset);
                        stSharedPar.WriteLine("*PARAM	GUID	NAME	DATATYPE	DATACATEGORY	GROUP	VISIBLE	DESCRIPTION	USERMODIFIABLE");
                        stSharedPar.WriteLine("#");
                    }
                    else
                    {
                        toBeDeferred = true;
                    }
                }

                string parName = newPar.Name;
                if (isType)
                {
                    if (newPar.Name.EndsWith("[Type]"))
                    {
                        parName = newPar.Name;
                    }
                    else
                    {
                        parName = newPar.Name + "[Type]";
                    }
                }

                string vis    = newPar.Visibility ? "1" : "0";
                string usrMod = newPar.UserModifiable ? "1" : "0";

                // Retain the same GUID if the existing file contains the same parameter name already. This is to keep consistent GUID, even for non-IfdGUID
                if (existingParDict.ContainsKey(parName))
                {
                    var existingPar = existingParDict[parName];
                    newPar.ParamGuid = existingPar.ParamGuid;
                }
                else if (isType)
                {
                    newPar.ParamGuid = Guid.NewGuid(); // assign new GUID for [Type] parameter if not existing
                }
                if (toBeDeferred)
                {
                    string parEntry = newPar.Param + "\t" + newPar.ParamGuid.ToString() + "\t" + parName + "\t" + newPar.ParamType + "\t" + newPar.DataCategory + "\t" + defaultGroupID.ToString()
                                      + "\t" + vis + "\t" + newPar.Description + "\t" + usrMod;
                    deferredParList.Add(parEntry);
                }
                else
                {
                    string parEntry = newPar.Param + "\t" + newPar.ParamGuid.ToString() + "\t" + parName + "\t" + newPar.ParamType + "\t" + newPar.DataCategory + "\t" + groupID.ToString()
                                      + "\t" + vis + "\t" + newPar.Description + "\t" + usrMod;
                    stSharedPar.WriteLine(parEntry);
                }
            }

            // Add items in the existing parameter dict that are not found in SharedParamFileDict, into the deferred list
            var disjunctPars = existingParDict.Where(x => !SharedParDict.ContainsKey(x.Key));

            foreach (KeyValuePair <string, SharedParameterDef> parDef in disjunctPars)
            {
                SharedParameterDef newPar  = parDef.Value;
                string             parName = newPar.Name;
                if (isType)
                {
                    if (newPar.Name.EndsWith("[Type]"))
                    {
                        parName = newPar.Name;
                    }
                    else
                    {
                        parName = newPar.Name + "[Type]";
                    }
                }
                string vis      = newPar.Visibility ? "1" : "0";
                string usrMod   = newPar.UserModifiable ? "1" : "0";
                string parEntry = newPar.Param + "\t" + newPar.ParamGuid.ToString() + "\t" + parName + "\t" + newPar.ParamType + "\t" + newPar.DataCategory + "\t" + defaultGroupID.ToString()
                                  + "\t" + vis + "\t" + newPar.Description + "\t" + usrMod;
                deferredParList.Add(parEntry);
            }
        }
        PsetDefinition Process(string schemaVersion, FileInfo PSDfileName)
        {
            PsetDefinition pset = new PsetDefinition();
            XDocument      doc  = XDocument.Load(PSDfileName.FullName);

            // Older versions of psd uses namespace!
            var        nsInfo = doc.Root.Attributes("xmlns").FirstOrDefault();
            XNamespace ns     = "";

            if (nsInfo != null)
            {
                ns = nsInfo.Value;
            }

            pset.Name       = doc.Elements(ns + "PropertySetDef").Elements(ns + "Name").FirstOrDefault().Value;
            pset.IfcVersion = doc.Elements(ns + "PropertySetDef").Elements(ns + "IfcVersion").FirstOrDefault().Attribute("version").Value.Replace(" ", "");
            if (pset.IfcVersion.StartsWith("2"))
            {
                if (pset.IfcVersion.Equals("2X", StringComparison.CurrentCultureIgnoreCase))
                {
                    pset.IfcVersion = "IFC" + pset.IfcVersion.ToUpper() + "2"; // BUG in the documentation. It ony contains "2x" instead of "2x2"
                }
                else
                {
                    pset.IfcVersion = "IFC" + pset.IfcVersion.ToUpper(); // Namespace cannot start with a number. e.g. make sure 2x3 -> IFC2x3
                }
            }
            else if (pset.IfcVersion.StartsWith("IFC4"))
            {
                pset.IfcVersion = schemaVersion.ToUpper();
            }

            if (doc.Element(ns + "PropertySetDef").Attribute("ifdguid") != null)
            {
                pset.IfdGuid = doc.Element(ns + "PropertySetDef").Attribute("ifdguid").Value;
            }
            // Get applicable classes
            IEnumerable <XElement> applicableClasses = from el in doc.Descendants(ns + "ClassName") select el;
            IList <string>         applClassesList   = new List <string>();

            foreach (XElement applClass in applicableClasses)
            {
                string className = ProcessPsetDefinition.removeInvalidNName(applClass.Value);
                if (!string.IsNullOrEmpty(className))
                {
                    applClassesList.Add(className);
                }
            }

            pset.ApplicableClasses = applClassesList;

            XElement applType = doc.Elements(ns + "PropertySetDef").Elements(ns + "ApplicableTypeValue").FirstOrDefault();

            if (applType != null)
            {
                string applicableType = applType.Value;
                if (!string.IsNullOrEmpty(applicableType) && !applicableType.Equals("N/A", StringComparison.InvariantCultureIgnoreCase))
                {
                    // Remove "SELF\" in the applicable type
                    if (applicableType.Contains("SELF\\"))
                    {
                        applicableType = applicableType.Replace("SELF\\", "");
                    }

                    string[] applTypeStr = applicableType.Split('/', '.', '=');
                    pset.ApplicableType = applTypeStr[0];
                    if (applTypeStr.Count() > 1)
                    {
                        pset.PredefinedType = applTypeStr[applTypeStr.Count() - 1].Replace("\"", "");
                    }

                    // If the applicable type contains more than 1 entry, add them into the applicable classes
                    string[] addClasses = pset.ApplicableType.Split(',');
                    if (addClasses.Count() > 1)
                    {
                        foreach (string addClass in addClasses)
                        {
                            string addClassTr = addClass.TrimStart().TrimEnd();
                            if (!pset.ApplicableClasses.Contains(addClassTr))
                            {
                                pset.ApplicableClasses.Add(addClassTr);
                            }
                        }
                    }
                }
            }

            IList <PsetProperty> propList = new List <PsetProperty>();
            var pDefs = from p in doc.Descendants(ns + "PropertyDef") select p;

            foreach (XElement pDef in pDefs)
            {
                PsetProperty       prop  = getPropertyDef(ns, pDef);
                SharedParameterDef shPar = new SharedParameterDef();
                if (prop == null)
                {
#if DEBUG
                    logF.WriteLine("%Error: Mising PropertyType data for {0}.{1}", pset.Name, pDef.Element(ns + "Name").Value);
#endif
                }
                else
                {
                    propList.Add(prop);
                }
            }
            pset.properties = propList;

            return(pset);
        }
        public static string processExistingParFile(string parFileName, bool isType, ref StreamWriter destFile)
        {
            IDictionary <string, SharedParameterDef> dictToFill;

            if (isType)
            {
                dictToFill = SharedParamFileTypeDict;
            }
            else
            {
                dictToFill = SharedParamFileDict;
            }

            string messageText = null;

            // Keep original data (for maintaining the GUID) in a dictionary
            using (StreamReader stSharedParam = File.OpenText(parFileName))
            {
                string line;
                while ((line = stSharedParam.ReadLine()) != null && !string.IsNullOrEmpty(line))
                {
                    // Copy content to the destination file
                    //destFile.WriteLine(line);

                    string[] token = line.Split('\t');
                    if (token == null || token.Count() == 0)
                    {
                        continue;
                    }

                    if (!token[0].Equals("PARAM"))
                    {
                        continue;
                    }

                    SharedParameterDef parDef = new SharedParameterDef();
                    parDef.Param = token[0];
                    try
                    {
                        parDef.ParamGuid = Guid.Parse(token[1]);
                    }
                    catch
                    {
                        // Shouldn't be here
                        continue;
                    }

                    if (string.IsNullOrEmpty(token[2]))
                    {
                        // Shouldn't be here
                        continue;
                    }
                    parDef.Name = token[2];

                    if (token[3] == null)
                    {
                        continue;
                    }

                    parDef.ParamType = token[3];

                    parDef.DataCategory = token[4];

                    int grp;
                    if (int.TryParse(token[5], out grp))
                    {
                        parDef.GroupId = grp;
                    }
                    else
                    {
                        continue;
                    }

                    parDef.Visibility = false;
                    if (!string.IsNullOrEmpty(token[6]))
                    {
                        int vis;
                        if (int.TryParse(token[6], out vis))
                        {
                            if (vis == 1)
                            {
                                parDef.Visibility = true;
                            }
                        }
                    }

                    if (!string.IsNullOrEmpty(token[7]))
                    {
                        parDef.Description = token[7];
                    }

                    parDef.UserModifiable = false;
                    if (!string.IsNullOrEmpty(token[8]))
                    {
                        int mod;
                        if (int.TryParse(token[8], out mod))
                        {
                            if (mod == 1)
                            {
                                parDef.UserModifiable = true;
                            }
                        }
                    }

                    try
                    {
                        dictToFill.Add(parDef.Name, parDef);
                    }
                    catch (ArgumentException exp)
                    {
                        messageText += "\n" + parDef.Name + ": " + exp.Message;
                    }
                }
            }
            return(messageText);
        }
        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("");
        }