/// <summary>
        /// Add the properties to the row object
        /// </summary>
        /// <param name="row">COBieAttributeRow holding the data</param>
        private void AddAttribute(COBieAttributeRow row)
        {
            //need a sheet and a row to be able to attach property to an object
            if ((ValidateString(row.RowName)) && (ValidateString(row.SheetName)))
            {
                switch (row.SheetName.ToLower())
                {
                    case "facility":
                        //set list if first time
                        if (IfcBuildings == null) IfcBuildings = Model.Instances.OfType<IfcBuilding>();
                        if (!((CurrentObject is IfcBuilding) && (CurrentObject.Name == row.RowName)))
                            CurrentObject = IfcBuildings.Where(b => b.Name.ToString().ToLower() == row.RowName.ToLower()).FirstOrDefault();
                        break;
                    case "floor":
                        if (IfcBuildingStoreys == null) IfcBuildingStoreys = Model.Instances.OfType<IfcBuildingStorey>();
                        if (!((CurrentObject is IfcBuildingStorey) && (CurrentObject.Name == row.RowName)))
                            CurrentObject = IfcBuildingStoreys.Where(b => b.Name.ToString().ToLower() == row.RowName.ToLower()).FirstOrDefault();
                        break;
                    case "space":
                        if (IfcSpaces == null) IfcSpaces = Model.Instances.OfType<IfcSpace>();
                        if (!((CurrentObject is IfcSpace) && (CurrentObject.Name == row.RowName)))
                            CurrentObject = IfcSpaces.Where(b => b.Name.ToString().ToLower() == row.RowName.ToLower()).FirstOrDefault();
                        break;
                    case "type":
                        if (IfcTypeObjects == null) IfcTypeObjects = Model.Instances.OfType<IfcTypeObject>();
                        if (!((CurrentObject is IfcTypeObject) && (CurrentObject.Name == row.RowName)))
                            CurrentObject = IfcTypeObjects.Where(b => b.Name.ToString().ToLower() == row.RowName.ToLower()).FirstOrDefault();
                        break;
                    case "spare":
                        if (IfcConstructionProductResources == null) IfcConstructionProductResources = Model.Instances.OfType<IfcConstructionProductResource>();
                        if (!((CurrentObject is IfcConstructionProductResource) && (CurrentObject.Name == row.RowName)))
                            CurrentObject = IfcConstructionProductResources.Where(b => b.Name.ToString().ToLower() == row.RowName.ToLower()).FirstOrDefault();
                        break;
                    case "component":
                        if (IfcElements == null) IfcElements = Model.Instances.OfType<IfcElement>();
                        if (!((CurrentObject is IfcElement) && (CurrentObject.Name == row.RowName)))
                            CurrentObject = IfcElements.Where(b => b.Name.ToString().ToLower() == row.RowName.ToLower()).FirstOrDefault();
                        break;
                    case "zone":
                        if (IfcZones == null) IfcZones = Model.Instances.OfType<IfcZone>();
                        if (!((CurrentObject is IfcZone) && (CurrentObject.Name == row.RowName)))
                            CurrentObject = IfcZones.Where(b => b.Name.ToString().ToLower() == row.RowName.ToLower()).FirstOrDefault();
                        break;
                    default:
                        CurrentObject = null;
                        break;
                }
               
                if (CurrentObject != null)
                {
                    if (ValidateString(row.Name)) 
                    {
                        IfcPropertySet ifcPropertySet = CheckIfExistOnMerge(row.ExtObject, row.ExtIdentifier);

                        if (ifcPropertySet == null)
                        {
                            return;
                        }

                        //Set Description
                        string description = "";
                        if (ValidateString(row.Description))
                            description = row.Description;


                        if ((ValidateString(row.Value)) &&
                            row.Value.Contains(":") &&
                            row.Value.Contains("(") &&
                            row.Value.Contains(")") 
                            )//only if we have a IfcPropertyTableValue defined by COBieDataAttributeBuilder
                        {
                            AddPropertyTableValue(ifcPropertySet , row.Name, description, row.Value, row.AllowedValues, row.Unit);
                        }
                        else if ((ValidateString(row.AllowedValues)) &&
                                //row.Value.Contains(":") && can be single value
                                (row.AllowedValues.Contains(":") ||
                                row.AllowedValues.Contains(",")
                                )
                                )//have a IfcPropertyEnumeratedValue
                        {
                            IfcValue[] ifcValues = GetValueArray(row.Value);
                            IfcValue[] ifcValueEnums = GetValueArray(row.AllowedValues);
                            IfcUnit ifcUnit = GetIfcUnit(row.Unit);
                            AddPropertyEnumeratedValue(ifcPropertySet, row.Name, description, ifcValues, ifcValueEnums, ifcUnit);
                        }
                        else
                        {
                            IfcValue ifcValue;
                            double number;
                            if (double.TryParse(row.Value, out number))
                                ifcValue = new IfcReal((double)number);
                            else if (ValidateString(row.Value))
                                ifcValue = new IfcLabel(row.Value);
                            else
                                ifcValue = new IfcLabel("");
                            IfcUnit ifcUnit = GetIfcUnit(row.Unit);
                            AddPropertySingleValue(ifcPropertySet, row.Name, description, ifcValue, ifcUnit);
                        }

                        //Add Category****
                        if (ValidateString(row.Category))
                        {
                            SetCategory(ifcPropertySet, row.Category);
                        }

                        //****************Note need this as last call Add OwnerHistory*************
                        if (ifcPropertySet != null)
                        {
                            //Add Created By, Created On and ExtSystem to Owner History. 
                            SetUserHistory(ifcPropertySet, row.ExtSystem, row.CreatedBy, row.CreatedOn);
                        }
                        //****************Note need SetOwnerHistory above to be last call, as XBim changes to default on any property set or changed, cannot use edit context as property set used more than once per row******
                    }
                    else
                    {
 #if DEBUG
                        Console.WriteLine("Failed to create attribute. No name : {0} value {1}", row.Name, row.ExtObject);
#endif
                    }
                    
                }
                else
                {
#if DEBUG
                    Console.WriteLine("Failed to create attribute. No object found to add too {0} value {1}", row.Name, row.ExtObject);
#endif
                }
                
            }
            else
            {
#if DEBUG
                Console.WriteLine("Failed to create attribute. No sheet or row name {0} value {1}", row.Name, row.ExtObject);
#endif
            }
            
        }
        /// <summary>
        /// Add Rows to the attribute sheet
        /// </summary>
        /// <param name="_attributes">The attribute Sheet to add the properties to its rows</param>
        /// <param name="propertySet">IfcPropertySet which is holding the IfcPropertySingleValue</param>
        /// <param name="propertySetValues">IEnumerable list of IfcPropertySingleValue to extract to the attribute sheet</param>
        private void ProcessAttributeRow(IfcPropertySet propertySet, IEnumerable<IfcSimpleProperty> propertySetValues)
        {
            //construct the rows
            foreach (IfcSimpleProperty propertySetSimpleProperty in propertySetValues)
            {
                if (propertySetSimpleProperty != null)
                {
                    string value = "";
                    string name = propertySetSimpleProperty.Name.ToString();
                    string extIdentifier = null;
                    string extObject = null;
                    


                    if (string.IsNullOrEmpty(name))
                    {
#if DEBUGATT
                        Console.WriteLine("Excluded attribute has no name");
#endif

                        continue; //skip to next loop item
                    }

                    IEnumerable<COBieAttributeRow> TestRow = _attributes.Rows.Where(r => r.Name == name && r.SheetName == RowParameters["Sheet"] && r.RowName == RowParameters["Name"]);
                    if (TestRow.Any()) continue; //skip to next loop item

                    //check what type we of property we have
                    IfcPropertySingleValue ifcPropertySingleValue = propertySetSimpleProperty as IfcPropertySingleValue;
                    //get value
                    if (ifcPropertySingleValue != null)
                    {
                        if (ifcPropertySingleValue.NominalValue != null)
                        {
                            value = ifcPropertySingleValue.NominalValue.Value != null ? ifcPropertySingleValue.NominalValue.Value.ToString() : string.Empty;
                            double num;
                            if (double.TryParse(value, out num)) value = num.ToString();
                            if ((string.IsNullOrEmpty(value)) || (string.Compare(value, ifcPropertySingleValue.Name.ToString(), true) == 0) || (string.Compare(value, "default", true) == 0))
                            {
#if DEBUGATT
                                Console.WriteLine("Excluded attribute {0}, has no value", name);
#endif
                                continue; //skip to next loop item
                            }

                        }

                    }

                    COBieAttributeRow attribute = new COBieAttributeRow(_attributes);
                    attribute.Unit = Constants.DEFAULT_STRING; //set initially to default, saves the else statements
                    attribute.AllowedValues = Constants.DEFAULT_STRING;
                    attribute.Description = Constants.DEFAULT_STRING;

                    if (ifcPropertySingleValue != null) //as we can skip on ifcPropertySingleValue we need to split ifcPropertySingleValue testing
                    {
                        if ((ifcPropertySingleValue.Unit != null))
                        {
                            attribute.Unit = COBieData<COBieAttributeRow>.GetUnitName(ifcPropertySingleValue.Unit);
                            
                        }
                    }

                    //Process properties that are not IfcPropertySingleValue
                    IfcPropertyEnumeratedValue ifcPropertyEnumeratedValue = propertySetSimpleProperty as IfcPropertyEnumeratedValue;
                    if (ifcPropertyEnumeratedValue != null)
                    {
                        string EnumValuesHeld = "";
                        if (ifcPropertyEnumeratedValue.EnumerationValues != null)
                        {
                            value = COBieData<COBieAttributeRow>.GetEnumerationValues(ifcPropertyEnumeratedValue.EnumerationValues);
                        }

                        //get  the unit and all possible values held in the Enumeration
                        if (ifcPropertyEnumeratedValue.EnumerationReference != null)
                        {
                            if (ifcPropertyEnumeratedValue.EnumerationReference.Unit != null)
                            {
                                attribute.Unit = COBieData<COBieAttributeRow>.GetUnitName(ifcPropertyEnumeratedValue.EnumerationReference.Unit);
                            }
                            EnumValuesHeld = COBieData<COBieAttributeRow>.GetEnumerationValues(ifcPropertyEnumeratedValue.EnumerationReference.EnumerationValues);
                            if (!string.IsNullOrEmpty(EnumValuesHeld)) attribute.AllowedValues = EnumValuesHeld;
                        }
                        //change the extIdentifier to the property set name and extObject to the property type
                        extIdentifier = propertySet.Name;
                        extObject = propertySetSimpleProperty.GetType().Name;
                    }

                    IfcPropertyBoundedValue ifcPropertyBoundedValue = propertySetSimpleProperty as IfcPropertyBoundedValue;
                    if (ifcPropertyBoundedValue != null)
                    {
                        //combine upper and lower into the value field
                        if (ifcPropertyBoundedValue.UpperBoundValue != null)
                            value = ifcPropertyBoundedValue.UpperBoundValue.ToString();
                        if (ifcPropertyBoundedValue.LowerBoundValue != null)
                        {
                            if (!string.IsNullOrEmpty(value))
                                value += " : " + ifcPropertyBoundedValue.LowerBoundValue.ToString();
                            else
                                value = ifcPropertyBoundedValue.LowerBoundValue.ToString();
                        }

                        if ((ifcPropertyBoundedValue.Unit != null))
                        {
                            attribute.Unit = COBieData<COBieAttributeRow>.GetUnitName(ifcPropertyBoundedValue.Unit);
                        }
                        //change the extIdentifier to the property set name and extObject to the property type
                        extIdentifier = propertySet.Name;
                        extObject = propertySetSimpleProperty.GetType().Name;
                    }

                    IfcPropertyTableValue ifcPropertyTableValue = propertySetSimpleProperty as IfcPropertyTableValue;
                    if (ifcPropertyTableValue != null)
                    {
                        if ((ifcPropertyTableValue.DefiningValues != null) &&
                            (ifcPropertyTableValue.DefinedValues != null) &&
                            (ifcPropertyTableValue.DefiningValues.Count() == ifcPropertyTableValue.DefinedValues.Count())
                            )
                        {
                            StringBuilder cellValue = new StringBuilder();
                            int i = 0;
                            foreach (var item in ifcPropertyTableValue.DefiningValues)
                            {
                                cellValue.Append("(");
                                cellValue.Append(item.ToString());
                                cellValue.Append(":");
                                cellValue.Append(ifcPropertyTableValue.DefinedValues[i].ToString());
                                cellValue.Append(")");
                                i++;
                            }
                            value = cellValue.ToString();
                            //get the unit definition
                            string cellUnit = "";
                            if (ifcPropertyTableValue.DefiningUnit != null)
                                cellUnit = COBieData<COBieAttributeRow>.GetUnitName(ifcPropertyTableValue.DefiningUnit);
                            else
                                cellUnit = "Unknown";
                            cellUnit += ":";
                            if (ifcPropertyTableValue.DefinedUnit != null)
                                cellUnit += COBieData<COBieAttributeRow>.GetUnitName(ifcPropertyTableValue.DefinedUnit);
                            else
                                cellUnit += "Unknown";
                            attribute.Unit = cellUnit;
                            if (!string.IsNullOrEmpty(ifcPropertyTableValue.Expression))
                                attribute.AllowedValues = ifcPropertyTableValue.Expression;
                        }
                        else
                        {
                            throw new ArgumentException("ProcessAttributeRow: IfcPropertyTableValue has unequal column numbers");
                        }
                        //change the extIdentifier to the property set name and extObject to the property type
                        extIdentifier = propertySet.Name;
                        extObject = propertySetSimpleProperty.GetType().Name;
                    }

                    IfcPropertyReferenceValue ifcPropertyReferenceValue = propertySetSimpleProperty as IfcPropertyReferenceValue;
                    if (ifcPropertyReferenceValue != null)
                    {
                        if (ifcPropertyReferenceValue.UsageName != null)
                            attribute.Description = (string.IsNullOrEmpty(ifcPropertyReferenceValue.UsageName.ToString())) ? Constants.DEFAULT_STRING : ifcPropertyReferenceValue.UsageName.ToString();

                        if (ifcPropertyReferenceValue.PropertyReference != null)
                        {
                            value = ifcPropertyReferenceValue.PropertyReference.ToString();
                            attribute.Unit = ifcPropertyReferenceValue.PropertyReference.GetType().Name;
                        }

                    }
                    IfcPropertyListValue ifcPropertyListValue = propertySetSimpleProperty as IfcPropertyListValue;
                    if (ifcPropertyListValue != null)
                    {
                        if (ifcPropertyListValue.ListValues != null)
                        {
                            value = COBieData<COBieAttributeRow>.GetEnumerationValues(ifcPropertyListValue.ListValues);
                        }

                        //get  the unit and all possible values held in the Enumeration
                        if (ifcPropertyListValue.Unit != null)
                            attribute.Unit = COBieData<COBieAttributeRow>.GetUnitName(ifcPropertyListValue.Unit);

                        //change the extIdentifier to the property set name and extObject to the property type
                        extIdentifier = propertySet.Name;
                        extObject = propertySetSimpleProperty.GetType().Name;
                    }


                    attribute.Name = propertySetSimpleProperty.Name.ToString();

                    //Get category
                    string cat = GetCategory(propertySet);
                    attribute.Category = (cat == Constants.DEFAULT_STRING) ? "Requirement" : cat;
                    
                    attribute.ExtIdentifier = string.IsNullOrEmpty(extIdentifier) ? propertySet.GlobalId.ToString() : extIdentifier;
                    if (string.IsNullOrEmpty(attribute.ExtIdentifier)) 
                        attribute.ExtIdentifier = Constants.DEFAULT_STRING;

                    attribute.ExtObject = string.IsNullOrEmpty(extObject) ? propertySet.Name.ToString() : extObject;
                    if (string.IsNullOrEmpty(attribute.ExtObject)) 
                        attribute.ExtObject = Constants.DEFAULT_STRING;

                    //passed properties from the sheet
                    attribute.SheetName = RowParameters["Sheet"];
                    attribute.RowName = RowParameters["Name"];
                    string createdBy = COBieData<COBieAttributeRow>.GetEmail( propertySet.OwnerHistory.OwningUser.TheOrganization, propertySet.OwnerHistory.OwningUser.ThePerson);
                    attribute.CreatedBy = (createdBy.Contains("unknown")) ? RowParameters["CreatedBy"] : createdBy; //check for incorrect made up email, if so then use parent CreatedBy
                    string onDate = COBieData<COBieAttributeRow>.GetCreatedOnDate(propertySet.OwnerHistory);
                    attribute.CreatedOn = (string.IsNullOrEmpty(onDate)) ? RowParameters["CreatedOn"] : onDate;
                    attribute.ExtSystem = (propertySet.OwnerHistory.OwningApplication != null) ? propertySet.OwnerHistory.OwningApplication.ApplicationFullName.ToString() : RowParameters["ExtSystem"];
                    if (string.IsNullOrEmpty(attribute.ExtSystem))
                        attribute.ExtSystem = Constants.DEFAULT_STRING;
                    
                    //value = NumberValueCheck(value, attribute);
                    attribute.Value = string.IsNullOrEmpty(value) ? Constants.DEFAULT_STRING : value;

                    attribute.Description = propertySetSimpleProperty.Description.ToString();
                    if (string.IsNullOrEmpty(attribute.Description)) //if no description then just use name property
                    {
                        attribute.Description = attribute.Name;
                    }

                    _attributes.AddRow(attribute);
                }
            }
        }