/// <summary>
        /// Creates property single value with specified type and default value of this type (0 for numeric types, empty string tor string types and false for bool types)
        /// </summary>
        /// <param name="pSetName">Property set name</param>
        /// <param name="propertyName">Property name</param>
        /// <param name="type">Type of the property</param>
        /// <returns>Property single value with default value of the specified type</returns>
        public static IfcPropertySingleValue SetPropertySingleValue(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyName, Type type)
        {
            if (typeof(IfcValue).IsAssignableFrom(type))
            {
                IfcValue value;
                if (typeof(IfcPositiveLengthMeasure).IsAssignableFrom(type))
                {
                    value = Activator.CreateInstance(type, 1.0) as IfcValue;
                }
                else
                {
                    value = Activator.CreateInstance(type) as IfcValue;
                }

                if (value != null)
                {
                    return(SetPropertySingleValue(obj, pSetName, propertyName, value));
                }
                else
                {
                    throw new Exception("Type '" + type.Name + "' can't be initialized.");
                }
            }
            else
            {
                throw new ArgumentException("Type '" + type.Name + "' is not compatible with IfcValue type.");
            }
        }
        public static IfcPropertySingleValue SetPropertySingleValue(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyName, IfcValue value)
        {
            IfcPropertySet pset  = GetPropertySet(obj, pSetName);
            IModel         model = null;

            if (pset == null)
            {
                model     = obj.ModelOf;
                pset      = model.Instances.New <IfcPropertySet>();
                pset.Name = pSetName;
                IfcRelDefinesByProperties relDef = model.Instances.New <IfcRelDefinesByProperties>();
                relDef.RelatingPropertyDefinition = pset;
                relDef.RelatedObjects.Add(obj);
            }

            //change existing property of the same name from the property set
            IfcPropertySingleValue singleVal = GetPropertySingleValue(obj, pSetName, propertyName);

            if (singleVal != null)
            {
                singleVal.NominalValue = value;
            }
            else
            {
                model     = obj.ModelOf;
                singleVal = model.Instances.New <IfcPropertySingleValue>(psv => { psv.Name = propertyName; psv.NominalValue = value; });
                pset.HasProperties.Add(singleVal);
            }

            return(singleVal);
        }
        public static IfcValue GetPropertyTableItemValue(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyTableName, IfcValue definingValue)
        {
            IfcPropertyTableValue table = GetPropertyTableValue(obj, pSetName, propertyTableName);

            if (table == null)
            {
                return(null);
            }
            XbimList <IfcValue> definingValues = table.DefiningValues;

            if (definingValues == null)
            {
                return(null);
            }
            if (!definingValues.Contains(definingValue))
            {
                return(null);
            }
            int index = definingValues.IndexOf(definingValue);

            if (table.DefinedValues.Count < index + 1)
            {
                return(null);
            }
            return(table.DefinedValues[index]);
        }
        public static IfcPropertyTableValue GetPropertyTableValue(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyTableName)
        {
            IfcPropertySet pset = GetPropertySet(obj, pSetName);

            if (pset != null)
            {
                return(pset.HasProperties.Where <IfcPropertyTableValue>(p => p.Name == propertyTableName).FirstOrDefault());
            }
            return(null);
        }
        public static void DeletePropertySingleValueValue(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyName)
        {
            IfcPropertySingleValue psv = GetPropertySingleValue(obj, pSetName, propertyName);

            if (psv == null)
            {
                return;
            }
            psv.NominalValue = null;
        }
        public static void RemovePropertySingleValue(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyName)
        {
            IfcPropertySet pset = GetPropertySet(obj, pSetName);

            if (pset != null)
            {
                IfcPropertySingleValue singleValue = pset.HasProperties.Where <IfcPropertySingleValue>(p => p.Name == propertyName).FirstOrDefault();
                if (singleValue != null)
                {
                    pset.HasProperties.Remove(singleValue);
                }
            }
        }
        public static VType GetPropertySingleValue <VType>(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyName) where VType : IfcValue
        {
            IfcPropertySet pset = GetPropertySet(obj, pSetName);

            if (pset != null)
            {
                IfcPropertySingleValue pVal = pset.HasProperties.Where <IfcPropertySingleValue>(p => p.Name == propertyName).FirstOrDefault();
                if (pVal != null && typeof(VType).IsAssignableFrom(pVal.NominalValue.GetType()))
                {
                    return((VType)pVal.NominalValue);
                }
            }
            return(default(VType));
        }
        public static void SetPropertyTableItemValue(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyTableName, IfcValue definingValue, IfcValue definedValue, IfcUnit definingUnit, IfcUnit definedUnit)
        {
            IfcPropertySet pset  = GetPropertySet(obj, pSetName);
            IModel         model = null;

            if (pset == null)
            {
                model     = obj.ModelOf;
                pset      = model.Instances.New <IfcPropertySet>();
                pset.Name = pSetName;
                IfcRelDefinesByProperties relDef = model.Instances.New <IfcRelDefinesByProperties>();
                relDef.RelatingPropertyDefinition = pset;
                relDef.RelatedObjects.Add(obj);
            }
            IfcPropertyTableValue table = GetPropertyTableValue(obj, pSetName, propertyTableName);

            if (table == null)
            {
                model = obj.ModelOf;
                table = model.Instances.New <IfcPropertyTableValue>(tb => { tb.Name = propertyTableName; });
                pset.HasProperties.Add(table);
                table.DefinedUnit  = definedUnit;
                table.DefiningUnit = definingUnit;
            }
            if (table.DefiningUnit != definingUnit || table.DefinedUnit != definedUnit)
            {
                throw new Exception("Inconsistent definition of the units in the property table.");
            }

            IfcValue itemValue = GetPropertyTableItemValue(obj, pSetName, propertyTableName, definingValue);

            if (itemValue != null)
            {
                itemValue = definedValue;
            }
            else
            {
                //if (table.DefiningValues == null) table.DefiningValues = new XbimList<IfcValue>();
                table.DefiningValues.Add(definingValue);
                //if (table.DefinedValues == null) table.DefinedValues = new XbimList<IfcValue>();
                table.DefinedValues.Add(definedValue);

                //check of integrity
                if (table.DefinedValues.Count != table.DefiningValues.Count)
                {
                    throw new Exception("Inconsistent state of the property table. Number of defined and defining values are not the same.");
                }
            }
        }
        /// <summary>
        /// Returns the propertyset of the specified name, null if it does not exist
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="pSetName"></param>
        /// <returns></returns>
        public static IfcPropertySet GetPropertySet(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, bool caseSensitive = true)
        {
            IfcRelDefinesByProperties rel = caseSensitive ?
                                            obj.IsDefinedByProperties.Where(r => r.RelatingPropertyDefinition.Name == pSetName).FirstOrDefault()
                : obj.IsDefinedByProperties.Where(r => r.RelatingPropertyDefinition.Name.ToString().ToLower() == pSetName.ToLower()).FirstOrDefault();

            if (rel != null)
            {
                return(rel.RelatingPropertyDefinition as IfcPropertySet);
            }
            else
            {
                return(null);
            }
        }
        public static List <IfcPropertySet> GetAllPropertySets(this Xbim.Ifc2x3.Kernel.IfcObject obj)
        {
            List <IfcPropertySet> result = new List <IfcPropertySet>();
            IEnumerable <IfcRelDefinesByProperties> rels = obj.IsDefinedByProperties;

            foreach (IfcRelDefinesByProperties rel in rels)
            {
                IfcPropertySet pSet = rel.RelatingPropertyDefinition as IfcPropertySet;
                if (pSet != null)
                {
                    result.Add(pSet);
                }
            }

            return(result);
        }
 public static void SetPropertyTableItemValue(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyTableName, IfcValue definingValue, IfcValue definedValue)
 {
     SetPropertyTableItemValue(obj, pSetName, propertyTableName, definingValue, definedValue, null, null);
 }
        public static Dictionary <IfcLabel, Dictionary <IfcIdentifier, IfcValue> > GetAllPropertySingleValues(this Xbim.Ifc2x3.Kernel.IfcObject obj)
        {
            Dictionary <IfcLabel, Dictionary <IfcIdentifier, IfcValue> > result = new Dictionary <IfcLabel, Dictionary <IfcIdentifier, IfcValue> >();
            IEnumerable <IfcRelDefinesByProperties> relations = obj.IsDefinedByProperties.OfType <IfcRelDefinesByProperties>();

            foreach (IfcRelDefinesByProperties rel in relations)
            {
                Dictionary <IfcIdentifier, IfcValue> value = new Dictionary <IfcIdentifier, IfcValue>();
                IfcLabel       psetName = rel.RelatingPropertyDefinition.Name ?? null;
                IfcPropertySet pSet     = rel.RelatingPropertyDefinition as IfcPropertySet;
                if (pSet == null)
                {
                    continue;
                }
                foreach (IfcProperty prop in pSet.HasProperties)
                {
                    IfcPropertySingleValue singleVal = prop as IfcPropertySingleValue;
                    if (singleVal == null)
                    {
                        continue;
                    }
                    value.Add(prop.Name, singleVal.NominalValue);
                }
                if (!result.ContainsKey(psetName))
                {
                    result.Add(psetName, value);
                }
            }
            return(result);
        }
        /// <summary>
        /// If the property value exists, returns the Nominal Value of the contents
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="pSetName"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static IfcValue GetPropertySingleNominalValue(this Xbim.Ifc2x3.Kernel.IfcObject obj, string pSetName, string propertyName)
        {
            IfcPropertySingleValue psv = GetPropertySingleValue(obj, pSetName, propertyName);

            return(psv == null ? null : psv.NominalValue);
        }
 //transformation function to convert/cast IFC2x3 data to appear as IFC4
 private static IIfcObjectDefinition RelatedObjectsToIfc4(IfcObject member)
 {
     return(member);
 }